xcode 互斥锁解锁异常失败

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14068816/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 02:24:42  来源:igfitidea点击:

Mutex unlock fails strangely

c++xcodemultithreadingmutexstd

提问by Jonas Eschmann

I am playing around with some sockets, thread and mutexes. My question concerns threads and mutexes:

我在玩一些套接字、线程和互斥锁。我的问题涉及线程和互斥锁:

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();
    }

}`

The main function is running in one thread, while the addNewSocket is called by another thread. The problem is, that when addNewSocket is called once (by the second thread), the next unlock by thread 1 (main) will fail with a strange "signal SIGABRT". I have worked two days on this now, but i did not manage to get it fixed, sadly. I hope you can help me.

main 函数在一个线程中运行,而 addNewSocket 由另一个线程调用。问题是,当 addNewSocket 被调用一次(由第二个线程)时,线程 1(主)的下一次解锁将失败,并出现一个奇怪的“信号 SIGABRT”。我现在已经为此工作了两天,但遗憾的是我没有设法解决它。我希望你能帮助我。

Edit: ConnectionHandler is a class, that has connectionList_mutex as a member.

编辑:ConnectionHandler 是一个类,它具有 connectionList_mutex 作为成员。

Edit: Sometimes i also get this error: "Assertion failed: (ec == 0), function unlock, file /SourceCache/libcxx/libcxx-65.1/src/mutex.cpp, line 44." but it occurs randomly.

编辑:有时我也会收到此错误:“断言失败:(ec == 0),函数解锁,文件 /SourceCache/libcxx/libcxx-65.1/src/mutex.cpp,第 44 行。” 但它是随机发生的。

Edit: This is the whole class (Reduced to a minimum, should be context independant to a certain degree, but crashes when i put it right after a client connected, and works if i put it right after the start:

编辑:这是整个课程(减少到最低限度,应该在一定程度上独立于上下文,但是当我在客户端连接后立即放置时会崩溃,如果我在开始后立即放置它会起作用:

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();

    }

}

采纳答案by Omnifarious

My guess is that your ConnectionHandlerobject is being destroyed somewhere. Also, you have defined ConnectionHandler::startin a silly way.

我的猜测是您的ConnectionHandler对象正在某处被销毁。此外,您ConnectionHandler::start以愚蠢的方式定义了。

First, ConnectionHandler::startshould be defined this way:

首先,ConnectionHandler::start应该这样定义:

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

The C++11 ::std::threadclass is perfectly capable of preserving the type of the function argument so there is no need to resort to void *.

C++11::std::thread类完全能够保留函数参数的类型,因此无需求助于void *.

Secondly, add in this code:

其次,添加以下代码:

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();
}

And change the constructor to read:

并将构造函数更改为:

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

This will show you when the ConnectionHandlerobject is being destroyed. And my guess is that your code is destroying it while your detached thread is still running.

这将显示ConnectionHandler对象何时被销毁。我的猜测是,当您的分离线程仍在运行时,您的代码正在破坏它。

The meptrthing is because operator <<has an overload for void *that prints out the pointer value. Printing out the pointer value for thiswill allow you to match up calls to the constructor and destructor if you're creating multiple ConnectionHandlerobjects.

meptr事情是因为operator <<有过载void *,打印出来的指针值。this如果您正在创建多个ConnectionHandler对象,打印出指针值将允许您匹配对构造函数和析构函数的调用。

Edit:Since it turned out I was correct, here is how I would recommend you write the play ConnectionHandler class:

编辑:事实证明我是正确的,以下是我建议您编写 play ConnectionHandler 类的方法:

#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;
}