使用Xcode的condition_variable抛出system_error-很好的VStudio

Mic*_*nda 4 c++ multithreading c++11

每次在Xcode中进行编译时,每次尝试等待condition_variable时都会收到错误消息。错误是“以类型为std :: __ 1 :: system_error的未捕获异常终止:条件变量等待失败:参数无效”

一切在Visual Studio 2013中都可以正常工作。如果我决定不等待多个线程的相同condition_variable,则代码可以正常工作。r

好的,代码。

main.cpp:

#include "ThreadPool.h"

int main(int argc, const char * argv[])
{
    ThreadPool pool;
    for (int i = 0; i < 10; ++i)
        pool.sendWork();

    std::this_thread::sleep_for(std::chrono::milliseconds(50000));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

线程池

#pragma once
#include <condition_variable>
#include <vector>
#include <thread>

class ThreadPool
{
protected:
    std::condition_variable     _condition;

private:
    std::vector<std::thread>    _threads;
    void threadLoop();

public:
    ThreadPool();
    void sendWork();
};
Run Code Online (Sandbox Code Playgroud)

ThreadPool.cpp:

#include "ThreadPool.h"

ThreadPool::ThreadPool()
{
    for (unsigned int i {0}; i < 10; ++i)
        _threads.push_back(std::thread(&ThreadPool::threadLoop, this));
}
void ThreadPool::threadLoop()
{
    std::mutex mutex;
    std::unique_lock<std::mutex> lock {mutex};
    _condition.wait(lock);            // This is where the crash happens
}

void ThreadPool::sendWork()
{
    _condition.notify_one();
}
Run Code Online (Sandbox Code Playgroud)

这是真实代码的主要简化,但是足以触发崩溃。

这应该工作吗?我在这里想念什么吗?

Chr*_*ung 5

您的互斥锁ThreadPool::threadLoop是一个局部变量。这意味着不同的线程锁定在不同的互斥锁上。这是无效的:条件变量绑定到特定的互斥锁,您必须在等待条件之前获取互斥锁的锁。

你应该在你的类中声明一个_mutex(或者更好的是,使用mutex_命名约定:下划线前缀标识符大多是保留的)成员变量ThreadPool,并始终锁定


T.C*_*.C. 5

更准确地说,规范的Requires部分condition_variable::wait()为(N3936§30.5.1[thread.condition.condvar] / p9):

void wait(unique_lock<mutex>& lock);
Run Code Online (Sandbox Code Playgroud)

要求lock.owns_lock()is truelock.mutex()被调用线程锁定,或者

—没有其他线程在等待该condition_variable对象,或者

- lock.mutex()返回每个的所有同时等待(通过提供的锁参数相同的值waitwait_forwait_until)线程。

因此,每个同时等待a的线程condition_variable必须传递相同的互斥量。从技术上讲,允许两个线程在condition_variable使用一个互斥锁的情况下等待,然后在两个等待都终止(并且没有线程在等待condition_variable)之后,让它们都使用不同的互斥锁在同一对象上等待。我不知道是否有任何实际的用例。

还请注意,std::condition_variable_any::wait()没有这样的要求。对提供的类型的唯一要求是它满足BasicLockable要求,这基本上意味着它具有lock()unlock()