condition_variable抛出system_error与Xcode - fine与VStudio

condition_variable throwing system_error with Xcode - fine with VStudio

本文关键字:Xcode VStudio fine error variable 抛出 system condition      更新时间:2023-10-16

每次我在Xcode编译时尝试等待我的condition_variable时都会出现错误。错误是"以未捕获的异常类型std::__1::system_error: condition_variable wait failed: Invalid argument结束"

在Visual Studio 2013中一切正常。如果我决定不等待来自多个线程的同一个condition_variable,代码就可以工作。Grrrr .

好的,代码。

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

ThreadPool.h

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

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

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

这应该工作吗?我遗漏了什么吗?

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

void wait(unique_lock<mutex>& lock);

要求: lock.owns_lock()true, lock.mutex()为锁定by调用线程,或者

-没有其他线程正在等待这个condition_variable对象或

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

因此,每个并发等待condition_variable的线程必须传入同一个互斥锁。从技术上讲,允许两个线程使用一个互斥锁等待一个condition_variable,然后在两个等待都结束后(并且没有线程在等待condition_variable),它们都使用不同的互斥锁等待同一个对象。我不知道这是否有任何现实的用例。

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

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

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