gpt4 book ai didi

c++ - pthread_cond_signal 的优雅线程终止证明有问题

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:00:57 24 4
gpt4 key购买 nike

我需要启动一堆线程,并想优雅地将它们关闭。

我正在尝试使用 pthread_cond_signal/pthread_cond_wait 来实现此目的,但遇到了问题。

这是我的代码。首先是 thread_main

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 );
}
}

现在我知道 pthread_cond_signal 不能保证唤醒哪个线程,所以我不能发信号并加入同一个循环。然而,这就是一切出错的地方。 pthread_cond_signal 如果没有线程在等待,则什么都不做,因此可能某些线程不会收到信号,因此不知道退出。

我该如何克服这个问题。

M.

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


最佳答案

首先,你必须改变你的谓词

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

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

那是 pthreads 的事,你必须防范 spurious wakeups .

现在你可以把它改成

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

因为在那次检查之后,你已经测试是否完成并退出,如果是的话,您所要做的就是向所有线程发送信号。

因此,在您的拆解函数中,将循环替换为:

pthread_cond_broadcast(&cond);

这应该确保所有线程都被唤醒,并将看到 finished 设置为 true 并退出。

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

另一种常见的模式是注入(inject)毒消息。毒消息只是您的线程可以识别的特殊消息,表示“停止”,您可以在队列中放置与线程数量一样多的这些消息。

关于c++ - pthread_cond_signal 的优雅线程终止证明有问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2317972/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com