POSIX条件变量

一.条件变量

当一个线程互斥地访问某个变量时,可能发现在其他线程改变状态之前,它什么也做不了.例如,一个线程访问队列时,发现队列为空,它只能等待,直到其他线程将一个节点添加到队列中,这种情况需要条件变量.

条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。

条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其它的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。一般说来,条件变量被用来进行线承间的同步。

二. 条件变量函数

pthread_cond_init

pthread_cond_destroy

pthread_cond_wait

pthread_cond_signal

pthread_cond_broadcast

三. 条件变量使用规范

(1)等待条件代码

pthread_mutex_lock(&mutex); //锁定互斥量

while(条件为假)

pthread_cond_wait(cond,mutex);

修改条件

pthread_mutex_unlock(&mutex);

(2)给条件发送信号代码

pthread_mutex_lock(&mutex);

设置条件为真

pthread_cond_signal(cond);

pthread_mutex_unlock(&mutex);

四. 使用条件变量解决生产者消费者问题

#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>

#include <semaphore.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

#define ERR_EXIT(m) 	do 	{			perror(m); 		exit(EXIT_FAILURE); 	}while(0)

#define CONSUMERS_COUNT 2
#define PRODUCERS_COUNT 4

pthread_cond_t g_cond;
pthread_mutex_t g_mutex;

// 创建的线程ID保存在g_thread中
pthread_t g_thread[CONSUMERS_COUNT+PRODUCERS_COUNT];

int nready=0;

///消费者
void* consume(void* arg)
{
	int num = (int)arg;
	int i;
	while(1)
	{
		pthread_mutex_lock(&g_mutex);
		while(nready == 0)
		{
			printf("(%d)begin wait a condition....\n",num);
			pthread_cond_wait(&g_cond,&g_mutex);
		}
		printf("(%d) end wait a condition....\n",num);
		printf("(%d) begin consume product ....\n",num);
		--nready;
		printf("(%d) end consume product ....\n",num);
		pthread_mutex_unlock(&g_mutex);
		sleep(1);
	}
	return NULL;
}

//// 生产者
void* produce(void* arg)
{
	int i;
	int num = (int)arg;
	while(1)
	{
		pthread_mutex_lock(&g_mutex);
		printf(" %d begin produce product ...\n",num);
		++nready;
		printf(" %d end produce product....\n",num);
		pthread_cond_signal(&g_cond);
		printf(" %d signal \n",num);
		pthread_mutex_unlock(&g_mutex);
		sleep(5);
	}
	return NULL;
}

int main(void )
{
	int i=0;

	//初始化互斥锁
	pthread_mutex_init(&g_mutex,NULL);
	//初始化条件变量
	pthread_cond_init(&g_cond,NULL);

	/// 创建消费者线程
	for(i=0;i<CONSUMERS_COUNT;++i)
		pthread_create(&g_thread[i],NULL,consume,(void*)i);
	sleep(1);
	/// 创建生产者线程
	for(i=0;i<PRODUCERS_COUNT;++i)
		pthread_create(&g_thread[CONSUMERS_COUNT+i],NULL,produce,(void*)i);
	// 等待线程的结束
	for(i=0;i<CONSUMERS_COUNT+PRODUCERS_COUNT;++i)
		pthread_join(g_thread[i],NULL);

	//销毁互斥锁和条件变量
	pthread_mutex_destroy(&g_mutex);
	pthread_cond_destroy(&g_cond);

	return 0;
}

问题分析:

//消费者

while(1)

{

pthread_mutex_lock(&g_mutex);

while(nready == 0)

{

pthread_cond_wait(&g_cond,&g_mutex);

}

--nready;

pthread_mutex_unlock(&g_mutex);

}

//生产者

while(1)

{

pthread_mutex_lock(&g_mutex);

++nready;

if(nready>0)

pthread_cond_signal(&g_cond);

pthread_mutex_unlock(&g_mutex);

}

1. 分析pthread_cond_wait(&g_cond,&g_mutex);所做的3件事

(1)对g_mutex进行解锁,(让别的线程改变条件变量,达到满足条件)

(2)等待条件,直到有线程想它发起通知

(3)重新对g_mutex进行加锁操作

2. 分析为什么使用while,而不用if语句

pthread_cond_signal 会向第一个等待的线程发起通知,如果没有任何一个线程处理等待状态,这个通知将被忽略

pthread_cond_broadcast 向所有等待线程发起通知

If  a  signal is delivered to a thread waiting for a condition variable,

upon return from the signal handler the thread resumes waiting  for  the

condition variable as if it was not interrupted, or it shall return zero

due to spurious wakeup.(虚假唤醒)

如果是虚假唤醒,条件并没有改变,需要用while再次判断条件是否满足.

时间: 2024-10-12 13:18:00

POSIX条件变量的相关文章

Linux多线程实践(8) --Posix条件变量解决生产者消费者问题

Posix条件变量 int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr); int pthread_cond_destroy(pthread_cond_t *cond); int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); int pthread_cond_timedwait(pthread_cond_t *cond

linux网络编程-posix条件变量(40)

举一个列子来说明条件变量: 假设有两个线程同时访问全局变量n,初始化值是0, 一个线程进入临界区,进行互斥操作,线程当n大于0的时候才执行下面的操作,如果n不大于0,该线程就一直等待. 另外一个线程也是进入临界区,修改n的值,当修改了n的值后,需要向等待中的线程发送通知,修改了n的值.但是现在存在这样的一个问题:当第一个线程进入临界区的时候,第一个线程一直处在等待n改变的状态,第二个线程是无法进入临界区的修改n的值的,这样第一个线程 就处于死锁了.上面这个问题可以时候条件变量来解决. 条件变量也

线程同步——条件变量

1.互斥量的存在问题:     互斥量是线程程序必需的工具,但它们并非万能的.例如,如果线程正在等待共享数据内某个条件出现,那会发生什么呢?它可以重复对互斥对象锁定和解锁,每次都会检查共享数据结构,以查找某个值.但这是在浪费时间和资源,而且这种繁忙查询的效率非常低. 在每次检查之间,可以让调用线程短暂地进入睡眠,比如睡眠三秒钟,但是因此线程代码就无法最快作出响应.真正需要的是这样一种方法:当线程在等待满足某些条件时使线程进入睡眠状态.一旦条件满足,就唤醒因等待满足特定条件而睡眠的线程.如果能够做

【转载】同步和互斥的POSIX支持(互斥锁,条件变量,自旋锁)

上篇文章也蛮好,线程同步之条件变量与互斥锁的结合: http://www.cnblogs.com/charlesblc/p/6143397.html 现在有这篇文章: http://blog.csdn.net/goodluckwhh/article/details/8564319 POSIX定义了一系列同步对象用于同步和互斥.同步对象是内存中的变量属于进程中的资源,可以按照与访问数据完全相同的方式对其进行访问.默认情况下POSIX定义的这些同步对象具有进程可见性,即同步对象只对定义它的进程可见:

并行编程之条件变量(posix condition variables)

在整理Java LockSupport.park()的东东,看到了个"Spurious wakeup",重新梳理下. 首先来个<UNIX环境高级编程>里的例子: [cpp] view plaincopy #include <pthread.h> struct msg { struct msg *m_next; /* ... more stuff here ... */ }; struct msg *workq; pthread_cond_t qready = P

POSIX 使用互斥量和条件变量实现生产者/消费者问题

boost的mutex,condition_variable非常好用.但是在Linux上,boost实际上做的是对pthread_mutex_t 和pthread_cond_t的一系列的封装.因此通过对原生态的POSIX 的mutex,cond的生成者,消费者的实现,我们可以再次体会boost带给我们的便利. 1. 什么是互斥量 互斥量从本质上说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁.对互斥量进行加锁以后,任何其他试图再次对互斥量加锁的线 程将会被阻塞直到当前线

生产者-消费者问题:介绍POSIX线程的互斥量和条件变量的使用

全局初始化互斥量和条件变量(不全局也行,但至少要对线程启动函数可见,这样才能使用.) static pthread_cont_t cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; 使用互斥量锁住一块代码方法如下(默认忽略pthread开头的函数的错误检查,即类似 int s = pthread_xxx(...); if (s != 0) { printErrorMsg(

线程同步(条件变量、信号量)以及死锁

死锁:指两个或两个以上进程(或线程)在执行过程中,因争夺资源而造成的一种互相等待现象,若无外力作用,它们都将无法继续推进下去. 例:交叉死锁:线程1获得了锁1,线程2获得了锁2,此时线程1调用lock想获得锁2,需挂起等待线程2释放锁2,而线程2也想获得锁1,也需挂起等待线程1释放锁1,此时两个线程都挂起等待 产生死锁的四个必要条件: (1):互斥条件(一个资源每次只能被一个进程或线程使用) (2):请求与保持条件(一个进程或线程因请求资源而阻塞时,对已获得的资源不释放) (3):不剥夺条件(此

详解条件变量

一年多过去啦,一段时间没有posix多线程的东西,又忘记的差不多略,我打记性咋这么差,丝毫记不起来怎么用啦,还是不如烂笔头啊. 大家都知道条件变量需要配合mutex一起使用,往往是这样的:lock->signal->unlock,  而另一边呢是: lock->wait->unlock. 在调用pthread_cond_wait(cond,mutex)时的执行顺序是这样的:1. 首先获取外面的mutex, 然后当前wait push 到一个等待的queue里面,然后释放锁.但是你看