user-0 提问: pthread_cond_wait作用？ 

回复:
user: user-1
content: 都讲太复杂了  pthread_cond_wait() 必须与pthread_mutex_lock() 配套使用。pthread_cond_wait()函数一进入wait状态就会自动release mutex。当其他线程（线程乙）通过pthread_cond_signal()或pthread_cond_broadcast，把该线程（线程甲）唤醒，使pthread_cond_wait()通过(返回)后 1，如果此时发信号pthread_cond_signal()的线程乙已经释放锁，线程甲自动获得该mutex。 2，如果此时发信号pthread_cond_signal()的线程乙还没有释放锁，则线程甲继续睡眠直到线程乙释放锁后，线程甲再获得mutex  就这么个道理

user: user-2
content: 引用 2 楼 user-3 的回复:你上面贴的代码（好像是我写的）有问题，似乎是我随手写的，没仔细检查。  先说一下条件变量的作用： 条件变量的作用是，仅当某个特定值满足某个条件时才执行后续的操作。  考虑下面这种情况：假设在线程1中，只有当（count > N） 时才需要执行后续操作，但这个count值是由其他线程（可能有多个）修改的，本线程并不知道什么时候才能满足条件。 如果需要后续的操作能即使响应，假使不使用条件变量，那么需要在一个循环中不断检测count值，这将极大的消耗CPU资源； 但如果用sleep等待，有可能会导致后续操作延误，而无法及时完成。  为了解决上面这种问题，于是引入了条件变量，在线程1中用下面这种方式来等待： pthread_cond_wait(&cond, &mutex)； 只要不满足预定的条件，那么上面这行将一直保持阻塞状态，不会占用任何CPU资源。  ================ 其他线程： 当操作count值的另外某个线程执行到另count = N时， // 1. 先给mutex加锁，用于包含cond变量，确保不会有其他线程重复触发条件激活的信号 pthread_mutex_lock(&mutex); // 2. 发个信号，告知条件就绪 pthread_cond_signal(&cond);  // 此时，pthread_cond_wait会激活，线程1开始支持后续操作 // 3. 解锁 pthread_mutex_lock(&mutex); -----------------------  线程1： 当pthread_cond_wait执行时，检查cond状态， a. 如果cond出于阻塞状态，先解锁mutex，并将该线程挂起在后台； b. 如果cond激活，那么就加锁mutex，并完成此次等待操作，允许执行线程1后续的工作。  具体流程是：  // 必须先加锁，才能执行pthread_cond_wait，否则会出现不可预知的结果 pthread_mutex_lock(&mutex);    while(1) // 如果需要反复执行 {         pthread_cond_wait(&cond, &mutex);  // 该行执行后，若cond为阻塞状态，则mutex将解锁         // 由于（b）步骤的操作，mutex此时出于加锁状态         // do some work               // finish work        if (满足某个终止条件）break;        // 由于是个循环，此时会返回到pthread_cond_wait行，注意此时mutex还是加锁状态 } pthread_mutex_unlock(&mutex); // 如果因为某些原因直接跳出了循环，需要解开被pthread_cond_wait加的锁   ======================================  在使用条件变量时有个注意事项，即必须确保线程1中的 pthread_cond_wait已经执行了之后，才能在其他线程中执行pthread_cond_sig操作，否则会出现不可预知的结果（我以前曾遇到过这种情况，找了很久才发现原因）。 可以在用pthread_create创建了线程1后。先 usleep几毫秒，然后在创建其他工作线程，这样可以确保取得预期的效果。 b. 如果cond激活，那么就加锁mutex，并完成此次等待操作，允许执行线程1后续的工作。  这句话建议修改一下，如果cond激活，得分两种： 1. 如果线城1已经获得锁，那就继续保持锁的状态  2. 如果线城1没有拿到锁，才加锁。

user: user-3
content: 引用b. 如果cond激活，那么就加锁mutex，并完成此次等待操作，允许执行线程1后续的工作。  这句话建议修改一下，如果cond激活，得分两种： 1. 如果线城1已经获得锁，那就继续保持锁的状态  2. 如果线城1没有拿到锁，才加锁。  感谢提醒。  不过我又考虑了一下，似乎在合理设计的情况下，不应出现在cond激活的同时，本线程也取得了锁的情况。 这是因为: （1） 当第一次调用pthread_cond_wait时，cond是阻塞的，此时本线程会释放锁，同时使线程阻塞在该函数上，会等待激活信号。 （2） 由于(1)的操作，当其他线程发出激活信号时，本线程是必然处于没拿到锁的状态，此时本线程将主动加锁(mutex_lock)，并将cond重置为阻塞状态。操作成功后再结束pthrad_cond_wait等待。 （3）由于(2)的操作，在下一次调用pthread_cond_wait之前，mutex锁将始终被本线程占有，其他线程没有机会解除cond的阻塞，所以又回到步骤（1）  在（1）～（3）这个循环中是不可能同时出现“cond激活，而本线程取得锁”的情况（除了pthread_cond_wait内部实现中的那次原子操作）。  如果出现那种情况，可能有两个原因： 1. 在其他线程中过早地调用了pthread_cond_signal，其他线程先激活了cond，而本线程还没来得及开始第一次cond_wait调用。 2. 其他线程在没先加锁的情况下直接调用了cond_signal。  如果出现以上两种行为，那么将可能导致无法预期的结果，在程序设计时就一定要避免。  =======================  另外，我在4楼贴的代码有bug，最初我只设计了一个【工作者线程】，生成随机数时用了rand()。后来考虑支持多个【工作者线程】，改换成了多线程安全的rand_r(&seed); 贴代码时忘了改main（）函数中的初始化种子的部分了。 需要将第52行的 srand(time(NULL)); 修改为 seed = time(NULL);  我另外写了一个实现多个工作者线程的完整版本，并修复了很多bug。 详见： http://bbs.csdn.net/topics/391922234

user: user-3
content: 不好意思，仔细看了一下，上面贴出的代码不是我写的（只是代码注释风格和我有点儿像）  贴一个使用条件变量的示例： 根据主贴中的代码，稍微做了一些改动，去掉了用scanf接受数据的代码，因为scanf使线程处于阻塞状态，不太容易看出条件变量的效果   /*  * test3.c  * Copyright 2016 Che Hongwei <htc.chehw@gmail.com>  * The MIT License (MIT)  *   */  #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <pthread.h> #include <time.h>  #define N 6  /* ************************  * 在使用条件变量时，尽可能地创建一个单独的互斥锁，将其仅用于同步条件变量cond，  * 假使为了省事，将该mutex用在了其他地方，如果实现的逻辑有出了差错，可能会出现不可预知的结果  * 为此，下面自定义了一个结构体，将cond和mutex强行捆绑在一起，避免误用  * */ typedef struct cond_mutex { 	pthread_cond_t c; 	pthread_mutex_t m; }cond_mutex_t;  /* ************************  * 初始化 互斥锁 和 条件变量   * */ cond_mutex_t cm =  { 	PTHREAD_COND_INITIALIZER, 	PTHREAD_MUTEX_INITIALIZER };     static void * wait_thread(void * param);   // 等待线程 static void * worker_thread(void * param); // 工作者线程  // 用一个mutex来同步对count 和 data 的操作 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static int count = 0; static int data[N];  unsigned int seed; volatile int quit = 0; // notify threads to quit  int main(int argc, char ** argv) { 	int rc; 	pthread_t th[2]; 	srand(time(NULL)); 	void * ret_code = NULL; 	 	// 创建等待线程 	rc = pthread_create(&th[0], NULL, wait_thread, NULL); 	if(0 != rc) 	{ 		perror("pthread_create"); 		exit(1); 	} 	usleep(5000); // 5 ms 	 	// 创建工作者线程 	rc = pthread_create(&th[1], NULL, worker_thread, NULL); 	if(0 != rc) 	{ 		perror("pthread_create"); 		exit(1); 	} 	 	 	char c = 0; 	printf("press enter to quit.\n"); 	while(1) 	{ 		scanf("%c", &c); 		if(c == '\n') break; 	} 	 	quit = 1; 	pthread_cond_broadcast(&cm.c); // 激活在所有线程中正在等待中的条件变量 	 	pthread_join(th[0], &ret_code); 	pthread_join(th[1], &ret_code); 	 	 	rc = (int)(long)ret_code; 	 	pthread_mutex_destroy(&mutex); 	pthread_cond_destroy(&cm.c); 	pthread_mutex_destroy(&cm.m); 	return rc;	 }  static void * worker_thread(void * param) { 	int value; 	while(!quit) 	{		 		value = rand_r(&seed) % 1000; 		pthread_mutex_lock(&mutex); // 先加锁之后，再修改data和count值 		if(quit) // 有可能在锁定等待期间被用户强行退出 		{ 			break; 		} 		data[count++] = value;		 		if(count == N) 		{ 			pthread_mutex_lock(&cm.m);			 			pthread_cond_signal(&cm.c); 			pthread_mutex_unlock(&cm.m);			 		} 		pthread_mutex_unlock(&mutex); // 解锁 		usleep(100000); // 100 ms; 	} 	pthread_exit((void *)(long)0); }  static void * wait_thread(void * param) { 	int i, sum; 	pthread_mutex_lock(&cm.m);	 	while(!quit) 	{ 		pthread_cond_wait(&cm.c, &cm.m); 		if(quit) break; //有可能是在等待期间被用户干预，强制退出的（在while中判断时quit可能还是0） 		 		pthread_mutex_lock(&mutex); // 先上锁，避免其他线程修改 data 和 count 值 		sum = 0; 		printf("data = "); 		for(i = 0; i < N; ++i) 		{ 			sum += data[i]; 			printf("%d, ", data[i]); 		} 		 		printf("average = %d\n", sum / N); 		count = 0; 		pthread_mutex_unlock(&mutex); 		 	} // end while 	 	pthread_mutex_unlock(&cm.m); 	 	pthread_exit((void *)(long)0); }

user: user-3
content: 补充： （上一条回复中有一点没表达清楚） 线程1中的 （a）和（b）步骤是 在 pthread_cond_wait函数内部实现的，对cond和mutex状态的改变是一个原子操作。

user: user-3
content: 你上面贴的代码（好像是我写的）有问题，似乎是我随手写的，没仔细检查。  先说一下条件变量的作用： 条件变量的作用是，仅当某个特定值满足某个条件时才执行后续的操作。  考虑下面这种情况：假设在线程1中，只有当（count > N） 时才需要执行后续操作，但这个count值是由其他线程（可能有多个）修改的，本线程并不知道什么时候才能满足条件。 如果需要后续的操作能即使响应，假使不使用条件变量，那么需要在一个循环中不断检测count值，这将极大的消耗CPU资源； 但如果用sleep等待，有可能会导致后续操作延误，而无法及时完成。  为了解决上面这种问题，于是引入了条件变量，在线程1中用下面这种方式来等待： pthread_cond_wait(&cond, &mutex)； 只要不满足预定的条件，那么上面这行将一直保持阻塞状态，不会占用任何CPU资源。  ================ 其他线程： 当操作count值的另外某个线程执行到另count = N时， // 1. 先给mutex加锁，用于包含cond变量，确保不会有其他线程重复触发条件激活的信号 pthread_mutex_lock(&mutex); // 2. 发个信号，告知条件就绪 pthread_cond_signal(&cond);  // 此时，pthread_cond_wait会激活，线程1开始支持后续操作 // 3. 解锁 pthread_mutex_lock(&mutex); -----------------------  线程1： 当pthread_cond_wait执行时，检查cond状态， a. 如果cond出于阻塞状态，先解锁mutex，并将该线程挂起在后台； b. 如果cond激活，那么就加锁mutex，并完成此次等待操作，允许执行线程1后续的工作。  具体流程是：  // 必须先加锁，才能执行pthread_cond_wait，否则会出现不可预知的结果 pthread_mutex_lock(&mutex);    while(1) // 如果需要反复执行 {         pthread_cond_wait(&cond, &mutex);  // 该行执行后，若cond为阻塞状态，则mutex将解锁         // 由于（b）步骤的操作，mutex此时出于加锁状态         // do some work               // finish work        if (满足某个终止条件）break;        // 由于是个循环，此时会返回到pthread_cond_wait行，注意此时mutex还是加锁状态 } pthread_mutex_unlock(&mutex); // 如果因为某些原因直接跳出了循环，需要解开被pthread_cond_wait加的锁   ======================================  在使用条件变量时有个注意事项，即必须确保线程1中的 pthread_cond_wait已经执行了之后，才能在其他线程中执行pthread_cond_sig操作，否则会出现不可预知的结果（我以前曾遇到过这种情况，找了很久才发现原因）。 可以在用pthread_create创建了线程1后。先 usleep几毫秒，然后在创建其他工作线程，这样可以确保取得预期的效果。

user: user-2
content: csdn的例子