Linux线程同步基础

以下内容引述至《Linux/Unix系统编程手册》

线程同步方式

互斥量 和 条件变量

互斥量

一般情况下,对每一共享资源(可能由多个先关变量组成)会使用不同的互斥量,每一个线程在访问同一资源时将采用如下协议

  • 针对共享资源锁定互斥量
  • 访问共享资源
  • 对互斥量解锁
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex *mutex);
int pthread_mutex_unlock(pthread_mutex *mutex);
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
int pthread_mutex_destroy(pthread_mutex_t *mutex);

互斥量类型

  • 同一线程不应对同一互斥量加锁两次
  • 线程不应对不为自己所拥有的互斥量解锁
  • 线程不应对一尚未锁定的互斥量做解锁动作

PTHREAD_MUTEX_NORMAL

该类型的互斥量不具有死锁检测功能,如果线程试图对已由自己锁定的互斥量枷锁,则发生死锁。

PTHREAD_MUTEX_ERRORCHECK

对此类互斥量的所有操作都会执行错误检查。这类互斥量运行起来比一般类型要慢

PTHREAD_MUTEX_RECURSIVE

递归互斥量维护有一个锁计数器。当线程第一次去的互斥时,会将锁计数器置1,后续由同一线程执行的每次加锁操作会递增锁计数器的数值,而解锁操作则递减计数器计数。只有当锁计数器降至0时,才会释放该互斥量。

条件变量

互斥量防止多个线程同时访问同一共享变量,条件变量允许一个线程就某个共享变量(或其他共享资源)的状态变化通知其他线程,并让其他线程等待这一通知。

#include <pthread.h>
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
int pthread_cond_timewait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);

int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
int pthread_cond_destroy(pthread_cond_t *cond);

条件变量与互斥量之间存在天然的关联关系

  1. 线程在准备检查共享变量状态时锁定互斥量;
  2. 检查共享变量的状态;
  3. 如果共享变量未处于预期状态,线程应在等待条件变量并进入休眠前解锁互斥量(以便其他线程能访问该共享变量);
  4. 当线程因为条件变量的通知而被再度唤醒时,必须对互斥量再次加锁,因为在典型情况下,线程会立即访问共享变量
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static ptherad_cond_t cond = PTHREAD_COND_INITIALIZER;
static int avail = 0;

// 生产者
s = pthread_mutex_lock(&mtx);
if(s!=0)
	// do log
avail ++;
s = pthread_mutex_unlock(&mtx);
if(s!=0)
	// do log
s = pthread_cond_signal(&cond);l
if(s!=0)
	// do log

// 消费者
for(;;){
	s = pthread_mutex_lock(&mtx);
	if(s!=0)
		// do log
	while(avail == 0) {
		s = pthread_cond_wait(&cond, &mtx);
		if(s !=0)
			// do log
	}
	while(avail > 0){
		avail--;
	}
	s = pthread_mutex_unlock(&mtx);
	if(s!=0)
		// do log
}

通用的设计原则:
必须由一个while循环,而不是if语句,来控制对pthread_cond_wait的调用。因为当代码从pthread_cond_wait()返回时,并不能确定判断条件的状态,所以应该立即重新检查判断条件,在条件不满足的情况下继续休眠等待;
从pthread_cond_wait返回时,之所以不能对判断条件的状态做任何假设,理由如下:

  • 其他线程可能会率先醒来,也许有多个线程在等待获取与条件变量相关的互斥量。
  • 设计时设置"宽松的"判断条件或许更为简单。有时,用条件变量来表征可能性而非确定性,在设计应用程序时会更加简单。
  • 可能会发生虚假唤醒的情况。在一些实现中,即使没有任何其他线程真地就条件变量发出信号,等待此条件变量的线程仍有可能醒来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值