我最近一直在使用pthreads,还有一件小事我还是不太了解。我知道条件变量旨在等待特定条件成立(或“发信号”)。我的问题是,这与普通的互斥体有何不同?
根据我的理解,当条件变为真时,条件变量不仅仅是一个具有额外逻辑的互斥锁来解锁另一个互斥锁(并再次将其锁定)?
Psuedocode示例:
mutex mymutex;
condvar mycond;
int somevalue = 0;
onethread()
{
lock(mymutex);
while(somevalue == 0)
cond_wait(mycond, mymutex);
if(somevalue == 0xdeadbeef)
some_func()
unlock(mymutex);
}
otherthread()
{
lock(mymutex);
somevalue = 0xdeadbeef;
cond_signal(mycond);
unlock(mymutex);
}
因此,此示例中的cond_wait解锁mymutex
,然后等待mycond
发出信号。
如果是这样,那么条件变量不仅仅是具有额外魔力的互斥量吗?或者我对互斥量和条件变量的基本基础有误解吗?
答案 0 :(得分:13)
两种结构完全不同。互斥体旨在提供对某种资源的序列化访问。条件变量意味着允许一个线程通知某个其他线程发生了某个事件。
答案 1 :(得分:12)
它们并不是具有额外魔力的互斥体,尽管在某些抽象(监视器用于java和C#)中,条件变量和互斥体组合成一个单元。条件变量的目的是避免总线等待/轮询,并提示应该“下一步”调度哪个线程的运行时间。考虑如何在没有条件变量的情况下编写此示例。
while(1) {
lock(mymutex)
if( somevalue != 0)
break;
unlock(mymutex);
}
if( somevalue == 0xdeadbeef )
myfunc();
你将坐在这个线程的紧密循环中,烧掉大量的cpu,并进行大量的锁争用。如果锁定/解锁互斥锁的价格足够便宜,那么您可能处于以下情况:其他地方甚至从未有机会获得锁定(尽管现实世界的互斥锁通常会区分拥有线程和拥有锁定,以及具有公平性的概念所以现实中不太可能发生这种情况。)
你可以通过坚持睡眠来减少忙碌的等待,
while(1) {
lock(mymutex)
if( somevalue != 0)
break;
unlock(mymutex);
sleep(1); // let some other thread do work
}
但是睡觉的好时间有多长?你基本上只是在猜测。运行时间也无法分辨你为什么要睡觉,或者你在等什么。条件变量使运行时至少可以在某种程度上了解当前对同一事件感兴趣的线程。
答案 2 :(得分:3)
简单的答案是,您可能希望从条件变量中唤醒多个线程,但是互斥锁只允许一个线程执行受保护的块。