【发布时间】:2016-04-21 09:28:28
【问题描述】:
我正在尝试将一个主线程与 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,并且它仅与除主线程(N = 1)之外的一个线程一起工作得很好。但是当适应 N>1 个线程时,就会发生上述错误。
Yam Marcovic 在 cmets 中说我不应该使用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
【问题讨论】:
-
从 main 中删除
lk[i%4].unlock(),对于初学者来说。 -
你到底想做什么?在执行结束时,您期望 in_main 变量的结果是什么?
-
>Remove lk[i%4].unlock() from main, for starters 这是给出错误的部分。但为什么?在这个例子中en.cppreference.com/w/cpp/thread/condition_variable你在等待后拥有了锁,所以需要解锁它
-
这段代码真的很难理解。你能评论一下吗?或者,更好的是,简化它?乍一看,您似乎在两个线程中等待/通知相同的条件变量,还是什么?
-
> 你想做什么?我正在尝试获得一定的打印顺序。 “输出线程,迭代 n”,其中 n % 4 == m,应该与线程 m 的打印交替,“在线程 m,迭代 l”。不同线程的打印之间的顺序无关紧要,只有该线程的打印与主线程的相对顺序。
标签: c++ multithreading stl