代码:
void *inc_func(void *arg)
{
pthread_mutex_lock(&mutex);
pthread_cond_signal(&count_threshold_cv);
sleep(1);
pthread_mutex_unlock(&mutex);
}
void *watch(void *arg)
{
pthread_mutex_lock(&mutex);
pthread_cond_wait(&count_threshold_cv,&mutex);
sleep(1);
pthread_mutex_unlock(&mutex);
}
int main()
{
pthread_t id[2];
pthread_create(&id[0],NULL,watch,NULL);
pthread_create(&id[1],NULL,inc_func,NULL);
int i;
for(i=0;i<2;i++)
pthread_join(id[i],NULL);
}
现在我们在每个线程中都有一个mutex_unlock
函数。还有一个锁定的互斥锁。为什么这不会导致undefined behaviour
。由于两个线程都试图解锁相同的互斥锁,导致一个互联网尝试解锁已经解锁的互斥锁。
编辑:pthread_cond_wait
释放要使用的第二个线程的mutex
。现在考虑第二个线程执行pthread_cond_signal
,这导致第一个线程重新获取mutex
。现在我们有两个具有相同mutex
锁的线程,因为两个线程都没有因为'sleep'函数而执行mutex_unlock
。我的理解错了吗?
答案 0 :(得分:1)
pthread_mutex_lock()
会阻止。如果互斥锁解锁则返回。
pthread_cond_wait()
在开始等待时解锁互斥锁,并在返回之前解锁。如果相关的互斥锁仍然被锁定,则返回可能会延迟。然后返回将延迟,直到互斥锁解锁。
将上述内容放在一起并将其应用到您显示的代码中,可以看到每个线程函数都以锁定后跟解锁(等等)开始,所以一切都很好。
参考示例代码:pthread_cond_wait()
在inc_func()
调用pthread_mutex_unlock()
时返回。
要成功处理示例代码描述的场景,您需要考虑两种特殊情况
pthread_cond_wait()
在没有发出信号的情况下返回。 要处理这两种情况,每个条件都应该有一个监视变量。
pthread_mutex_t mutex = ...
pthread_cond_t count_threshold_cv = ...
int signalled = 0;
void *inc_func(void *arg)
{
pthread_mutex_lock(&mutex);
pthread_cond_signal(&count_threshold_cv);
signalled = 1;
pthread_mutex_unlock(&mutex);
}
void *watch(void *arg)
{
pthread_mutex_lock(&mutex);
while (0 == signalled)
{
pthread_cond_wait(&count_threshold_cv,&mutex);
}
pthread_mutex_unlock(&mutex);
}
int main(void)
{
pthread_t id[2];
pthread_create(&id[0],NULL,watch,NULL);
pthread_create(&id[1],NULL,inc_func,NULL);
int i;
for(i=0;i<2;i++)
pthread_join(id[i],NULL);
}
答案 1 :(得分:1)
如果订单确实是
watch
先运行并锁定(inc_func
等待)watch
使用pthread_cond_wait
等待解锁互斥文件并根据documentation 进行阻止
这些函数以原子方式释放互斥锁并导致调用线程 在条件变量cond上阻止;
这允许以下
inc_func
获取互斥锁然后发出信号(此时互斥锁尚未释放)inc_func
发布互斥锁watch
个简历:成功返回后,互斥锁已被锁定,并由调用线程拥有。
如果inc_func
的代码首先执行而未切换到watch
inc_func
锁定互斥锁inc_func
信号,但没有人发出信号,这没关系。inc_func
解锁互斥锁watch
锁定互斥锁