条件变量:
1.当一个线程互斥地访问某个变量时,他可能发现其他线程改变状态之前,他什么也不做了
2.例如:一个线程访问队列时,发现队列为空,他只能等待,只到其他线程将一个节点添加到队列中,这种情况就需要用到条件变量
对于解决无界缓冲区比较好的选择
函数:
pthread_cond_init初始化一个条件变量
pthread_cond_destroy 销毁一个条件变量
pthread_cond_wait在一个条件上等待 做三件事:1,对mutex进行解锁,2,等待条件,直到有线程向他发起通知 3,,重新对mutex进行加锁操作
pthread_cond_signal当一个条件满足时向一个线程发送信号,如果没有任何一个线程处于等待线程条件的状态,这个信号将会被忽略
pthread_cond_broadcast向等待的所有等待的线程发送通知
条件变量的使用规范:
等待条件代码
pthread_mutex_lock(&mutex)
while(条件为假)//用while的原因:因为pthread_cond_wait会 被虚假唤醒,然而条件变量却没有改变,所以用while可以再次判定条件变量(另外他会自动重启与while无关)
pthread_cond_wait(cond,mutex);
修改条件
pthread_mutex_unlock(&mutex)
给条件发送信号代码
pthread_mutex_lock(&mutex)
设置条件为真
pthread_cond_signal(cond);
pthread_mutex_unlock(&mutex);
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#define ERR_EXIT(m)\
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
}while(0)
#define CONSUMERS_COUNT 2
#define PRODUCERS_COUNT 1
pthread_mutex_t g_mutex;
pthread_cond_t g_cont;
int iread;
pthread_t g_thread[CONSUMERS_COUNT+PRODUCERS_COUNT];
void* produce(void* arg)
{
while(1)
{
pthread_mutex_lock(&g_mutex);
iread++;
printf("product iread=%d\n",iread);
pthread_cond_signal(&g_cont);
printf("produce is produat\n");
pthread_mutex_unlock(&g_mutex);
sleep(3);
}
return NULL;
}
void* consumer(void* arg)
{
while(1)
{
pthread_mutex_lock(&g_mutex);
printf("consumer iread =%d\n",iread);
while(iread==0)
{
pthread_cond_wait(&g_cont, &g_mutex);
printf("iread is changed\n");
}
iread--;
sleep(1);
pthread_mutex_unlock(&g_mutex);
}
return NULL;
}
int main()
{
int i;
pthread_mutex_init(&g_mutex,NULL);
pthread_cond_init(&g_cont,NULL);
for(i=0; i< PRODUCERS_COUNT;i++)
{
pthread_create(&g_thread[i],NULL,produce,(void*)i);
}
for(i=0; i< CONSUMERS_COUNT;i++)
{
pthread_create(&g_thread[i+ PRODUCERS_COUNT],NULL,consumer,(void*)i);
}
for(i=0; i< PRODUCERS_COUNT+CONSUMERS_COUNT;i++)
{
pthread_join(g_thread[i],NULL);
}
pthread_mutex_destroy(&g_mutex);
pthread_cond_destroy(&g_cont);
return 0;
}