Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;线程:在条件_变量等待后无法解锁数组中的互斥锁_C++_Multithreading_Stl - Fatal编程技术网

C++ C++;线程:在条件_变量等待后无法解锁数组中的互斥锁

C++ C++;线程:在条件_变量等待后无法解锁数组中的互斥锁,c++,multithreading,stl,C++,Multithreading,Stl,我正在尝试将一个主线程与N个子线程同步。经过一些阅读,我使用了condition\u variable和unique\u lock。但是,在OS X中,我总是得到错误条件\u变量::wait:mutex not locked:Operation not allowed或unique\u lock::unlock:not locked:Operation not allowed。在Linux中,我只得到Operation not allowed 更清楚地说:我的目标是获得一系列打印: main t

我正在尝试将一个主线程与N个子线程同步。经过一些阅读,我使用了
condition\u variable
unique\u lock
。但是,在OS X中,我总是得到错误
条件\u变量::wait:mutex not locked:Operation not allowed
unique\u lock::unlock:not locked:Operation not allowed
。在Linux中,我只得到
Operation not allowed

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

main thread, passing to 0
thread 0, passing back to main
main thread, passing to 0
thread 0, passing back to main
...
对于四个线程中的每一个

我根据中的示例改编了代码。本例在
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;
}

您多次尝试
解锁
您的互斥锁!仔细查看代码:

 for(int i=0; i < N_ITER*N_THREADS; i++) {
        int tid=i % N_THREADS; // Thread id
因此,当
i=0
时,
lk[0]
中的互斥锁被解锁,然后当
i=4
时,则
tid=4%4
再次
tid=0
时,您将再次解锁它<代码>标准::系统错误在这种情况下被抛出

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


另外,通常在处理数组索引时,惯例是使用
size\u t
而不是
int

我发现了问题所在。这个问题帮助了我

构造
唯一锁
也会获取
唯一锁
。因此,它必须在循环内完成,就在调用
wait
之前。函数
fun
看起来是一样的,但是
main
现在看起来是这样的:

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
    for(int i=0; i<N_THREADS; 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);
        // DO NOT construct, therefore acquire, a unique_lock
    }

    for(int i=0; i < N_ITER*N_THREADS; i++) {
        int tid=i % N_THREADS; // Thread id
        // Acquire the unique_lock here
        unique_lock<mutex> lk(mtx[tid]);
        // Wait until in_main[tid] is true
        cv[tid].wait(lk, [=]{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.unlock(); // error here, but example uses unlock
        cv[tid].notify_one();
    }
    for(int i=0; i<N_THREADS; i++)
        t[i].join();
    return 0;
}
intmain(intargc,char*argv[]){
//我们将创建N_线程。创建互斥体和
//所有的条件变量。
互斥mtx[N_线程];
条件变量cv[N_螺纹];
螺纹t[N_螺纹];
//创建N_线程唯一的_锁,以便将条件_变量用于每个线程
//线

对于(int i=0;iRemove
lk[i%4]。首先,从main中解锁()
。您到底想做什么?在执行结束时,您的in_main变量会有什么结果?>删除lk[i%4]。解锁()从main开始,这是产生错误的部分。但是为什么呢?在本例中,等待后您拥有锁,因此需要解锁。这段代码真的很难理解。您可以对其进行注释吗?或者,更好的是,简化它?乍一看,您似乎在两个线程中等待/通知相同的条件变量,或者其他什么你想做什么?我想得到打印的特定顺序。“外线程,迭代n”,其中n%4==m,应该与线程m的打印交替,“内线程m,迭代l”。不同线程的打印之间的顺序并不重要,只是该线程的打印与主线程的相对顺序。谢谢您的回答。但是:“当i=0时,lk[0]中的互斥锁被解锁,然后当i=4时,tid=4%4,所以再次tid=0,您再次解锁!”当i=0时,主线程设置为_main[0]为false。当i=4时,主线程应该在_main[0]中等待再次为真。在继续并再次解锁之前,另一个线程应该更改它。另外,我的印象是,执行条件变量::wait会给线程一个锁定的锁。如果bool修改在锁内,它真的没有定义吗?你说的“另一个线程应该更改它”是什么意思显然不是这样,如果你在_main中设置了防护,那么就没问题了。wait是防护吗?我链接的示例说是,但显然不是。另外,“显然不是”,显然是,看看示例输出。(注意,我将数组初始化为false,因此生成的线程开始打印)很抱歉,这不符合逻辑。我添加了一个编译和运行时获得的示例输出。它似乎通过修改布尔值将控制权交还给了主线程。
 for(int i=0; i < 40; i++) {
        int tid=i % 4; // Thread id
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
    for(int i=0; i<N_THREADS; 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);
        // DO NOT construct, therefore acquire, a unique_lock
    }

    for(int i=0; i < N_ITER*N_THREADS; i++) {
        int tid=i % N_THREADS; // Thread id
        // Acquire the unique_lock here
        unique_lock<mutex> lk(mtx[tid]);
        // Wait until in_main[tid] is true
        cv[tid].wait(lk, [=]{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.unlock(); // error here, but example uses unlock
        cv[tid].notify_one();
    }
    for(int i=0; i<N_THREADS; i++)
        t[i].join();
    return 0;
}