8

私はいくつかのソケット、スレッド、ミューテックスで遊んでいます。私の質問はスレッドとミューテックスに関するものです:

int ConnectionHandler::addNewSocket(){

    this->connectionList_mutex.lock();
    std::cout << "test1" << std::endl;
    this->connectionList_mutex.unlock();

    return 0;
}

int ConnectionHandler::main(){
    while(true){
        this->connectionList_mutex.lock();
        std::cout << "test2" << std::endl;
        this->connectionList_mutex.unlock();
    }

}`

main関数は1つのスレッドで実行されていますが、addNewSocketは別のスレッドによって呼び出されています。問題は、addNewSocketが(2番目のスレッドによって)1回呼び出されると、スレッド1(メイン)による次のロック解除が奇妙な「シグナルSIGABRT」で失敗することです。私は今これに2日間取り組んできましたが、残念ながらそれを修正することができませんでした。あなたが私を助けてくれることを願っています。

編集:ConnectionHandlerは、connectionList_mutexをメンバーとして持つクラスです。

編集:時々私はこのエラーも受け取ります:「アサーションに失敗しました:(ec == 0)、関数のロック解除、ファイル/SourceCache/libcxx/libcxx-65.1/src/mutex.cpp、44行目」しかし、それはランダムに発生します。

編集:これはクラス全体です(最小限に抑えられ、ある程度コンテキストに依存しないはずですが、クライアントが接続された直後に配置するとクラッシュし、開始直後に配置すると機能します:

class ConnectionHandler{
public:
    ConnectionHandler();
    int addNewSocket();
private:
    int main();
    static void start(void * pThis);

    std::mutex connectionList_mutex;
};

ConnectionHandler::ConnectionHandler(){
    std::thread t(&this->start, this);
    t.detach();
}
void ConnectionHandler::start(void * pThis){
    ConnectionHandler *handlerThis;
    handlerThis = (ConnectionHandler *)pThis;
    handlerThis->main();
}


int ConnectionHandler::addNewSocket(){

    this->connectionList_mutex.lock();
    std::cout << "test1" << std::endl;
    this->connectionList_mutex.unlock();

    return 0;
}

int ConnectionHandler::main(){
    while(true){
        this->connectionList_mutex.lock();
        std::cout << "test2" << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
        this->connectionList_mutex.unlock();

    }

}
4

1 に答える 1

6

私の推測では、あなたのConnectionHandlerオブジェクトはどこかで破壊されています。また、あなたはConnectionHandler::startばかげた方法で定義しました。

まず、次のConnectionHandler::startように定義する必要があります。

void ConnectionHandler::start(ConnectionHandler * pThis){
    pThis->main();
}

C ++ 11::std::threadクラスは、関数の引数の型を完全に保持できるため、に頼る必要はありませんvoid *

次に、次のコードを追加します。

void ConnectionHandler::~ConnectionHandler(){
    const void * const meptr = this;
    this->connectionList_mutex.lock();
    ::std::cout << "ConnectionHandler being destroyed at " << meptr << ::std::endl;
    this->connectionList_mutex.unlock();
}

そして、コンストラクターを次のように変更します。

ConnectionHandler::ConnectionHandler(){
    const void * const meptr = this;
    ::std::cout << "ConnectionHandler being created at " << meptr << ::std::endl;
    std::thread t(&this->start, this);
    t.detach();
}

ConnectionHandlerこれにより、オブジェクトが破棄されたときに表示されます。そして、私の推測では、デタッチされたスレッドがまだ実行されている間に、コードがコードを破壊していると思います。

これは、ポインタ値を出力するためのオーバーロードがあるmeptrためです。のポインタ値を出力すると、複数のオブジェクトを作成している場合に、コンストラクタとデストラクタの呼び出しを一致させることができます。operator <<void *thisConnectionHandler

編集:私が正しかったことがわかったので、playConnectionHandlerクラスを作成することをお勧めします。

#include <iostream>
#include <atomic>
#include <thread>
#include <chrono>
#include <mutex>

class ConnectionHandler {
 public:
   ConnectionHandler();
   ~ConnectionHandler();
   ConnectionHandler(const ConnectionHandler &) = delete;
   const ConnectionHandler &operator =(const ConnectionHandler &) = delete;

   int addNewSocket();

 private:
   int main();
   static void start(ConnectionHandler * pThis);

   ::std::mutex connectionList_mutex;
   volatile ::std::atomic_bool thread_shutdown;
   ::std::thread thread;
};

ConnectionHandler::ConnectionHandler()
     : thread_shutdown(false), thread(&this->start, this)
{
}

ConnectionHandler::~ConnectionHandler()
{
   thread_shutdown.store(true);
   thread.join();
}

void ConnectionHandler::start(ConnectionHandler * pThis){
   pThis->main();
}

int ConnectionHandler::addNewSocket(){
   ::std::lock_guard< ::std::mutex> lock(connectionList_mutex);
   ::std::cout << "test1" << ::std::endl;

   return 0;
}

int ConnectionHandler::main(){
   while(!thread_shutdown.load()){
      ::std::lock_guard< ::std::mutex> lock(connectionList_mutex);
      ::std::cout << "test2" << ::std::endl;
      ::std::this_thread::sleep_for(::std::chrono::milliseconds(100));

   }
   return 0;
}
于 2012-12-28T13:20:29.053 に答える