什么时候mutex不够,还需要condition variable?

原文链接:http://blog.csdn.net/scanerki/article/details/8850282


假设有共享的资源sum,与之相关联的mutex 是lock_s.假设每个线程对sum的操作很简单的,与sum的状态无关,比如只是sum++.那么只用mutex足够了.程序员只要确保每个线程操作前,取得lock,然后sum++,再unlock即可.

每个线程的代码将像这样

add(){
	pthread_mutex_lock(lock_s);
	sum++;
	pthread_mutex_unlock(lock_s);
}
如果操作比较复杂,假设线程t0,t1,t2的操作是sum++,而线程t3则是在sum到达100的时候,打印出一条信息,并对sum清零.这种情况下, 如果只用mutex, 则t3需要一个循环,每个循环里先取得lock_s,然后检查sum的状态,如果sum>=100,则打印并清零,然后unlock.如果 sum<100,则unlock,并sleep()本线程合适的一段时间.
这个时候,t0,t1,t2的代码不变,t3的代码如下

print(){
	while (1)
	{
		pthread_mutex_lock(lock_s);
		if(sum<100){
			printf(“sum unreach 100!”);
			pthread_mutex_unlock(lock_s);
		}
		else{
			pthread_mutex_unlock(lock_s);
			my_thread_sleep(100);
			return OK;
		}
	}
}
这种办法有两个问题
1) sum在大多数情况下不会到达100,那么对t3的代码来说,大多数情况下,走的是else分支,只是lock和unlock,然后sleep().这浪费了CPU处理时间.
2) 为了节省CPU处理时间,t3会在探测到sum没到达100的时候sleep()一段时间.这样却又带来另外一个问题,亦即t3响应速度下降.可能在sum到达200的时候,t4才会醒过来.
3) 这样,程序员在设置sleep()时间的时候陷入两难境地,设置得太短了节省不了资源,太长了又降低响应速度.真是难办啊!

这个时候,condition variable内裤外穿,从天而降,拯救了焦头烂额的你.
你首先定义一个condition variable.

pthread_cond_t cond_sum_ready=PTHREAD_COND_INITIALIZER;
t0,t1,t2的代码只要后面加两行,像这样

add(){
	pthread_mutex_lock(lock_s);
	sum++;
	pthread_mutex_unlock(lock_s);
	
	if(sum>=100)
		pthread_cond_signal(&cond_sum_ready);
}
而t3的代码则是

print{
	pthread_mutex_lock(lock_s);
	while(sum<100)
		pthread_cond_wait(&cond_sum_ready, &lock_s);
		
	printf(“sum is over 100!”);
	sum=0;
	pthread_mutex_unlock(lock_s);
	return OK;
}
注意两点:
1) 在thread_cond_wait()之前,必须先lock相关联的mutex, 因为假如目标条件未满足,pthread_cond_wait()实际上会unlock该mutex, 然后block,在目标条件满足后再重新lock该mutex, 然后返回.
2) 为什么是while(sum<100),而不是if(sum<100) ?这是因为在pthread_cond_signal()和pthread_cond_wait()返回之间,有时间差,假设在这个时间差内,还有另外一个线程t4又把sum减少到100以下了,那么t3在pthread_cond_wait()返回之后,显然应该再检查一遍sum的大小.这就是用 while的用意.

mutex(互斥锁)和condition variable(条件变量)是操作系统中常用的同步机制,用于协调多个线程之间的访问和通信。 互斥锁(mutex)是一种保护共享资源的机制。当一个线程获得了互斥锁后,其他线程需要等待该锁被释放才能继续执行。只有一个线程可以持有互斥锁,这样可以确保在任意时刻只有一个线程访问共享资源,避免竞态条件(race condition)的发生。 条件变量(condition variable)用于线程之间的通信。它允许一个线程等待某个特定条件的发生,而不需要浪费CPU资源进行无谓的轮询。当某个条件不满足时,线程可以调用条件变量的等待(wait)操作,使自己进入等待状态,同时释放互斥锁。当其他线程改变了条件并发出信号(signal)时,等待的线程会被唤醒并重新获得互斥锁,然后继续执行。 通常,使用互斥锁和条件变量可以实现复杂的同步和通信需求。比如,一个生产者-消费者模型中,生产者线程生产数据并放入缓冲区,消费者线程从缓冲区中取出数据进行消费。生产者和消费者线程需要共享一个缓冲区,并且需要协调彼此的操作。互斥锁可以用来保护对缓冲区的访问,条件变量可以用来实现当缓冲区为空或满时的等待和唤醒操作。 总结起来,互斥锁用于保护共享资源的访问,条件变量用于线程之间的等待和唤醒操作,它们通常结合使用来实现复杂的同步和通信需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值