我正在尝试将一个主线程与 N 个子线程同步。阅读之后,我使用了 condition_variable
和 unique_lock
。但是,在 OS X 中,我总是收到错误 condition_variable::wait: mutex not locked: Operation not permitted
或 unique_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/