Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.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++ pthread_cond_信号的优美线程终止证明有问题_C++_Multithreading_Pthreads_Mutex - Fatal编程技术网

C++ pthread_cond_信号的优美线程终止证明有问题

C++ pthread_cond_信号的优美线程终止证明有问题,c++,multithreading,pthreads,mutex,C++,Multithreading,Pthreads,Mutex,我需要发射一束线,并想把他们优雅地下来 我试图使用pthread\u cond\u signal/pthread\u cond\u wait来实现这一点,但遇到了一个问题 这是我的密码。首先是主线程 static void *thrmain( void * arg ) { // acquire references to the cond var, mutex, finished flag and // message queue ..... while( tr

我需要发射一束线,并想把他们优雅地下来

我试图使用
pthread\u cond\u signal
/
pthread\u cond\u wait
来实现这一点,但遇到了一个问题

这是我的密码。首先是主线程

static void *thrmain( void * arg )
{
    // acquire references to the cond var, mutex, finished flag and
    // message queue
    .....

    while( true )
    {
        pthread_mutex_lock( &lock );

        if ( msq.empty() )
        {
            // no messages so wait for one.
            pthread_cond_wait( &cnd, &lock );
        }

        // are we finished.
        if ( finished )
        {
            // finished so unlock the mutex and get out of here
            pthread_mutex_unlock( &lock );
            break;
        }

        if ( !msg.empty() )
        {
            // retrieve msg
            ....

            // finished with lock
            pthread_mutex_unlock( &lock );

            // perform action based on msg
            // outside of lock to avoid deadlock
        }
        else
        {
            // nothing to do so we're
            // finished with the lock.
            pthread_mutex_unlock( &lock );
        }
    }

    return 0;
}
现在,这一切看起来都很好和漂亮(无论如何对我来说)

因此,为了拆除线程,我有这个方法

void teardown()
{
    // set the global finished var
    pthread_mutex_lock( &lock );
    finished = true;
    pthread_mutex_unlock( &lock );

    // loop over the threads, signalling them
    for ( int i = 0 ; i < threads.size() ; ++i )
    {
        // send a signal per thread to wake it up
        // and get it to check it's finished flag
        pthread_cond_signal( &cnd );
    }

    // need to loop over the threads and join them.
    for ( int i = 0 ; i < threads.size() ; ++i )
    {
        pthread_join( threads[ i ].tid, NULL );
    }
}
void拆卸()
{
//设置全局变量
pthread_mutex_lock(&lock);
完成=正确;
pthread_mutex_unlock(&lock);
//在线程上循环,向它们发送信号
对于(int i=0;i
现在我知道,
pthread\u cond\u signal
不能保证它唤醒哪个线程,所以我不能发出信号并加入同一个循环。然而,这正是问题所在
pthread_cond_signal
如果没有线程等待,则不会执行任何操作,因此可能某些线程没有收到信号,因此不知道退出

我该怎么过来呢

M

*****更新******* 请不要发帖子说我应该使用pthread_cond_broadcast,因为它表现出完全相同的行为。它只会唤醒一个实际上正在等待cond变量的线程。在此期间处理并稍后返回等待的任何线程都将错过该信号,并且将被忽略



您想使用
pthread\u cond\u broadcast()
而不是
pthread\u cond\u signal()
。前者解除对所有在给定条件下等待的线程的阻塞。

我从未直接使用过pthreads(我更喜欢Boost.threads),但我认为您应该调用
pthread\u cancel
,而不是
pthread\u cond\u signal
,首先,您必须将谓词从

if ( msq.empty() ) {
  // no messages so wait for one.
  pthread_cond_wait( &cnd, &lock );
}

这是一个pthreads的东西,你必须警惕自己

现在您可以将其更改为

while ( msq.empty()  && !finished) {
  // no messages so wait for one.
  pthread_cond_wait( &cnd, &lock );
}
因为在该检查之后,您已经测试是否设置了finished,如果设置了finished,则退出, 你所要做的就是给所有的线程发信号

因此,在拆卸函数中,将循环替换为:

pthread_cond_broadcast(&cond);
这将确保所有线程都被唤醒,并将看到
finished
设置为
true
并退出

即使线程没有卡在
pthread\u cond\u wait
中,这也是安全的。如果线程正在处理消息,它们将不会收到唤醒信号,但是它们将完成该处理,再次进入循环,并看到
finished==false
并退出


另一种常见的模式是注入有害消息。有毒消息只是线程可以识别的一条特殊消息,它意味着“停止”,您可以在队列中放置与线程数量相同的消息。

我想您应该在调用pthread\u cond\u信号后解锁互斥锁。另外,在获取互斥锁后进入条件等待之前,请检查“完成”的条件。希望这有帮助

如果线程在调用后进入等待状态,它仍然会失败。这就是重点。。只有当cond变量上有线程阻塞时,它才会执行任何操作。如果没有阻塞,则该线程将不知道如何退出。。这就是问题的症结所在,@Tronic:原始海报仍然应该使用
pthread\u cond\u broadcast()
,而不是
pthread\u cond\u signal()
循环。我的答案不完整(对于手头的问题,需要在等待之前而不是之后检查
finished
),但没有错;博士,但你可能是对的。在更复杂的情况下,使用cond_广播变得复杂,取消可能更好。不。我特别不想调用pthread_cancel,这就是为什么我要实现一个优雅的关闭。取消线程会遇到比我试图解决的问题更严重的问题。您可以将pthreads设置为仅在取消点取消,这样可以顺利退出。感谢-1,不过:(即使只在取消点取消也是危险的;在许多情况下,它可能导致资源泄漏。您能更具体地说一下吗?当然,函数中的返回语句可能会导致资源泄漏,但考虑到要小心进行适当的处理,我不明白为什么取消会成为一个问题。不。这只是一个更优雅的r。)epeat与前面的答案相同。pthread_cond_broadast将仅向实际在cond var上等待的线程发出信号。如果任何线程都在忙于处理,那么当最终到达等待调用时,它们将不会醒来。如果它们在忙处理,它们已经被唤醒,并且将在下一个循环中退出,因为完成了b是真的。自从你的眼泪落下设置完成后保持互斥锁,您就安全了。如上所述,当您向线程发送信号时,线程不需要处于等待状态。如果使用有毒消息方法,则根本不需要完成标志。您应该保持锁,直到发送完信号,我友好的手册页上说
解锁互斥锁并在条件v时挂起变量是以原子方式完成的。因此,如果所有线程总是在向条件发送信号之前获取互斥体,这就保证了在线程锁定互斥体和等待条件变量之间不能向条件发送信号(从而忽略条件)。
请参见此处以获取参考
pthread_cond_broadcast(&cond);