C++ 线程 : cannot unlock mutex in array after condition_variable wait

标签 c++ multithreading stl

我正在尝试将一个主线程与 N 个子线程同步。阅读之后,我使用了 condition_variableunique_lock。但是,在 OS X 中,我总是收到错误 condition_variable::wait: mutex not locked: Operation not permittedunique_lock::unlock: not locked: Operation not permitted。在 Linux 中,我只得到 Operation not permitted

更清楚一点:我的目标是获得一系列打印:

main thread, passing to 0
thread 0, passing back to main
main thread, passing to 0
thread 0, passing back to main
...

对于四个线程中的每一个。

我改编了 http://en.cppreference.com/w/cpp/thread/condition_variable 中的示例代码.此示例在 wait 之后使用了 unlock,并且它只与除 main (N=1) 之外的一个线程一起工作。但是当适应与 N>1 线程一起工作时,就会发生上述错误。

Yam Marcovic 在评论中说我不应该使用 unlock。但是,为什么 cppreference 示例要使用它呢?为什么它在一个主线程和一个其他线程上运行良好?

代码如下:

#include <cstdio>
#include <thread>
#include <mutex>
#include <condition_variable>

using namespace std;

constexpr int N_THREADS = 4;
constexpr int N_ITER = 10;

bool in_main[N_THREADS] = {false};

void fun(mutex *const mtx, condition_variable *const cv, int tid){
    for(int i=0; i<N_ITER; i++) {
        unique_lock<mutex> lk(*mtx);
        // Wait until in_main[tid] is false
        cv->wait(lk, [=]{return !in_main[tid];});
        // After the wait we own the lock on mtx, which is in lk
        printf("thread %d, passing back to main\n", tid);
        in_main[tid] = true;
        lk.unlock(); // error here, but example uses unlock
        cv->notify_one();
    }
}

int main(int argc, char *argv[]) {
    // We are going to create N_THREADS threads. Create mutexes and
    // condition_variables for all of them.
    mutex mtx[N_THREADS];
    condition_variable cv[N_THREADS];
    thread t[N_THREADS];
    // Create N_THREADS unique_locks for using the condition_variable with each
    // thread
    unique_lock<mutex> lk[N_THREADS];
    for(int i=0; i<N_THREADS; i++) {
        lk[i] = unique_lock<mutex>(mtx[i]);
        // Create the new thread, giving it its thread id, the mutex and the
        // condition_variable,
        t[i] = thread(fun, &mtx[i], &cv[i], i);
    }

    for(int i=0; i < N_ITER*N_THREADS; i++) {
        int tid=i % N_THREADS; // Thread id
        // Wait until in_main[tid] is true
        cv[tid].wait(lk[tid], [=]{return in_main[tid];});
        // After the wait we own the lock on mtx[tid], which is in lk[tid]
        printf("main thread, passing to %d\n", tid);
        in_main[tid] = false;
        lk[tid].unlock(); // error here, but example uses unlock
        cv[tid].notify_one();
    }
    for(int i=0; i<N_THREADS; i++)
        t[i].join();
    return 0;
}

示例输出:

thread 0, passing back to main
main thread, passing to 0
thread 1, passing back to main
thread 0, passing back to main
main thread, passing to 1
thread 2, passing back to main
thread 1, passing back to main
main thread, passing to 2
thread 2, passing back to main
thread 3, passing back to main
main thread, passing to 3
main thread, passing to 0
thread 3, passing back to main
libc++abi.dylib: terminating with uncaught exception of type std::__1::system_error: unique_lock::unlock: not locked: Operation not permitted
Abort trap: 6

最佳答案

您正在尝试 unlock你的互斥量很多次!仔细看代码:

 for(int i=0; i < N_ITER*N_THREADS; i++) {
        int tid=i % N_THREADS; // Thread id

哪里N_ITER是 10 和 N_THREADS总是 4,因为它们是 constexpr
我们得到:

 for(int i=0; i < 40; i++) {
        int tid=i % 4; // Thread id

所以,当i = 0 lk[0] 中的互斥锁解锁,然后当i=4然后tid = 4%4又一次tid = 0你又在解锁它! std::system_error在这种情况下被抛出。

此外,为什么所有这些 C 指针都是如此?它不像它们中的任何一个可以在任何时候为空..切换到引用..

此外,通常在处理数组索引时,惯例是使用 size_t而不是 int .

关于C++ 线程 : cannot unlock mutex in array after condition_variable wait,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36765395/

相关文章:

python - 串行读/写代码中可能存在的竞争条件

c++ - 从函数按值返回STL vector 的有效方法

c++ - set_difference 和 set_intersection 同时进行

multithreading - 尝试重新定义 IO::Tee::PRINT 以确保线程安全

c++ - 通过linux终端将数据发送到另一个进程的stdin

素数搜索中的 C++ 数组

c++ - #Visual Studio 中的警告

java - 永远不会结束的话题

c++ - 无法访问 C++ std::set 中对象的非常量成员函数

c++ - 存储无效指针是否自动未定义的行为?