我有一个简单的应用程序,可以与不同的硬件接口。对于每个硬件,我针对一个独特的监视器函数生成pthread_t
,共计6个线程:1个经理线程和5个工作线程。
每个线程都有一个共同的初始化例程,它等待管理器线程通过以下方式唤醒它:
pthread_mutex_lock(&mMutex);
pthread_cond_wait(&mMutex, &condVar);
pthread_mutex_lock(&mMutex);
然后主线程通过一次发出一个信号来唤醒所有线程:
pthread_cond_wait(&mMutex1, &condVar1);
pthread_cond_wait(&mMutex2, &condVar2);
...
pthread_cond_wait(&mMutex5, &condVar5);
代码实际上运行正常,但这是因为我对时机很幸运。当主/管理器线程发出pthread_cond_signal
时,存在远程但存在的机会,即线程尚未完成初始化。我需要找到一种方法来保证每个条件变量都由其各自的工作线程对其进行wait
调用。
我总是可以创建一个在相应的互斥锁中设置的状态布尔值,但据我所知,我不能在一条指令中原子地执行set
和wait
操作。我也可以使用pthread_barrier_t
,但这可以保证所有线程在进行相应的wait
调用之前都是一两条指令。
是否有一种经过验证的方法可以确定已经进行了wait
调用,或者我是否需要采用某种定时等待循环/检查方式?
谢谢。
答案 0 :(得分:3)
我总是可以创建一个在相应的互斥锁中设置的状态布尔值,但据我所知,我无法在一条指令中自动执行set和wait操作。
这是正确的方法 - 你可以以原子方式执行set和wait操作,因为条件变量与互斥锁交互的方式。当您执行pthread_cond_wait()
操作时,必须将您传入的互斥锁锁定。如果在执行pthread_cond_signal()
时相应地锁定了相同的互斥锁,则在信令线程解锁互斥锁之前,等待线程不会被唤醒。
因此,以下代码可以满足您的需求:
// Flag indicating if the worker thread is waiting or not
bool waiting = false;
...
// Worker thread code
... do stuff ...
while (!condition_is_not_satisfied())
{
pthread_mutex_lock(&mutex);
waiting = true;
pthread_cond_wait(&cond, &mutex);
waiting = false;
pthread_mutex_unlock(&mutex);
}
...
// Signalling thread code
pthread_mutex_lock(&mutex);
if (waiting)
{
// Worker thread is waiting -- signal it to wake up
pthread_cond_signal(&cond);
}
else
{
// Worker thread has not yet entered the wait state -- do something else
}
pthread_mutex_unlock(&mutex);
答案 1 :(得分:1)
条件变量应始终与受互斥锁保护的谓词配对。在这种情况下,您的谓词可以只是一个简单的标志:在工作线程中,它看起来像:
pthread_mutex_lock(&mMutex);
while (!woken)
pthread_cond_wait(&mMutex, &condVar);
pthread_mutex_unlock(&mMutex);
在经理线程中,它看起来像:
pthread_mutex_lock(&mMutex);
woken = 1;
pthread_cond_signal(&condVar);
pthread_mutex_unlock(&mMutex);
这里,如果管理器线程首先获取互斥锁,那么当工作者获取互斥锁时,将设置标志,并且它将不会等待;如果工作人员首先获得互斥锁,则经理将无法获取互斥锁并设置标志,直到工作人员被保持在pthread_cond_wait
。