本来打算用一个形象的生活情况来比喻条件互斥的,但想了再想实在没有想到比较科学贴切的比喻.
那还是开门见山来说吧.
Condition Variable无论在C/C++还是C#,JAVA语言里,都会搭配一个Mutex来用.
我们知道Mutex的普通意义上是维持一个互斥变量,从而保证一个或一组操作的原子性.
同样,简单的说Mutex加在Condition Variable上也是为了保证它的原子性了.
Condition Variable,有条件的唤醒机制.最经典不过的就是生产--消息者模型了.
但有一个细节,消费者需要有"产品"才能继续它的消费行为,因此当消费者发现"产品"
被消费完了?它该怎么办?
没错,普通情况下它就会进入等待挂起状态.但这一状态什么时候才能结束?又是谁来告诉它
有"产品"可消费呢?没错,这个时候消费者就是在等待"有产品可消费"这一条件才会苏醒.
这个时候我们就能用到Condition Variable了.
上代码:#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct msg{
struct msg *next;
int num;
};
struct msg *head;
pthread_cond_t has_product;//Condition Variable
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;//互斥锁初始化
void *consumer(void *p)
{
struct msg *mp;
for(;;){
pthread_mutex_lock(&lock);//保证生产与消费的互斥,消费者取得lock
while(head == NULL)
pthread_cond_wait(&has_product,&lock);
//其实while这一过程并不是必需的, pthread_cond_wait这一过程已经可以实现等待-执行可程了.但由于线程被唤醒的情况有多种,我们需要的是head!=NULL这种情况才会继续执行.而且pthread_cond_wait()这个方法还会有一个内在的执行过程,在pthread_cond_wait()这一过程中我们必需保证lock的持有,当线程刷新了等待队列之后,在被持起之前lock会被释放.
当另一个线程调用pthread_cond_signal()唤醒之前需要先把lock给释放了,因为调用pthread_cond_signal()后,消费进程需要重新通过pthread_cond_wait()这个方法获得lock,然后执行逻辑处理代码,最后消费进程释放lock.
mp = head;
head = mp->next;
pthread_mutex_unlock(&lock);//释放lock
printf("Consumer %d\n",mp->num);
free(mp);
sleep(rand()%5);
}
}
void *producer(void *p)
{
struct msg *mp;
for(;;){
mp = malloc(sizeof(struct msg));
mp->num = rand() % 1000+1;
printf("Produce %d\n",mp->num);
pthread_mutex_lock(&lock);//为保证操作的原子性获得lock
mp->next = head;
head = mp;
pthread_mutex_unlock(&lock);//释放lock
pthread_cond_signal(&has_product);//唤醒消费进程
sleep(rand()%5);
}
}
int main(int argc,char *argv[])
{
pthread_t pid,cid;
srand(time(NULL));
cid = pthread_create(&cid,NULL,consumer,NULL);
pid = pthread_create(&pid,NULL,producer,NULL);
sleep(5);
pthread_join(pid,NULL);
pthread_join(cid,NULL);
return 0;
}
上面文字解释是关键部份,主要是pthread_cond_wait()这一内在执行过程比较重要.
分享到:
相关推荐
C++11中的各种mutex, lock对象,实际上都是对posix的mutex,condition的封装。不过里面也有很多细节值得学习。 std::mutex 先来看下std::mutex: 包增了一个pthread_mutex_t __m_,很简单,每个函数该干嘛...
详细介绍了线程同步条件变量condition_variable的使用和它的源码,涉及到unique_lock, mutex, lock_guard, 虚假唤醒和惊群效应。
通过一个标志位来处理的方式虽然可以实现效果,但是还不够安全,极有可能有多条线程同时操作一个全局变量,导致资源争夺问题,为了保证安全,可以在此基础上加上对应的锁来处理同步问题,比如加上互斥锁 mutex,就...
需求: 有三条线程,可以分别输出A、B、C字符,现想办法控制输出顺序,使得顺序为ABCABC......ABC[共10组],并且每条线程只能启动一次,不能多次启动。 需要3条线程输出不同的字符,分别为A、B、C,并且顺序要固定...
图文并茂Mutex性能问题解析,理解Mutex的机制,对于理解共享池的争用,意义巨大
游戏外挂 多开用的上 mutex 互斥体 game dll
To be noticed, wai() will unlock mutex and will continue when the relevant mutex be unlocked. Signal() will not release the mutex which means it will go ahead without waiting for anything.
Laravel开发-laravel-mutex 拉拉维尔的静音储物柜。
ucos-ii中互斥信号mutex建立源码
linux 内核 mutex.c 源码分析实例,我的实例主要先初始化了一个互斥体m,然后获取互斥体的锁(解锁),紧接着释放互斥体的锁(解锁)。最后释放互斥体。中间通过输出m.count来显示互斥体的状态。
LinuxC线程同步Mutex实例,让你一目了然
c++11多线程库中互斥库模块的使用方式,介绍了mutex类和time_mutex类的使用方式
linux mutex锁的使用demo,适合新手学习。
使用Mutex对象实现多线程同步,打印输出结果,对比非同步情况下的输出结果,对比明显,更容易理解Mutex对象实际意义。
linux上C++互斥线程Mutex的代码及解释,很有用
C# 使用Mutex和AutoResetEvent类处理多线程同步与互斥,调试并完善了网上文档的代码。经测试能很好地实现要求,但还有一些地方不是特别明白,都写在注释中了,请高手给予指点。
mutex在线程中的使用 简单操作 全局变量 在vs2008 c++
2. 封装了boost的condition_variable,使其使用方法很接近Windows的Event。其优势在于能跨平台使用。 3. 封装了boost的mutex,能跨平台使用。 4. 封装了boost的mutex的scoped_lock,能跨平台使用。
利用mutex object编写的多线程运用程序, 可以直接运行,可以手动改变线程优先级, 很直观。
利用mutex互斥变量实现线程同步机制,并输出循环1000000次所用的时间