一、条件变量
条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待"条件变量的条件成立"而挂起;另一个线程使"条件成立"(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。
pthread_cond_t cond;//定义
初始化条件变量:
1. pthread_cond_init(&cond, NULL); 动态初始化。
2. pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 静态初始化。
阻塞等待条件:
pthread_cond_wait(&cond, &mutex);
作用:
1) 阻塞等待条件变量满足
2) 解锁已经加锁成功的信号量 (相当于 pthread_mutex_unlock(&mutex))
3) 当条件满足,函数返回时,重新加锁信号量
(相当于,pthread_mutex_lock(&mutex);)
pthread_cond_signal(): 唤醒阻塞在条件变量上的 (至少)一个线程。
pthread_cond_broadcast(): 唤醒阻塞在条件变量上的 所有线程。
注销一个条件变量需要调用pthread_cond_destroy(),
只有在没有线程在该条件变量上等待的时候,才能注销这个条件变量,
否则返回EBUSY。API定义如下:
int pthread_cond_destroy(pthread_cond_t *cond)
二、Demo:生产者消费者模型
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
void err_thread(int ret, char *str)
{
if(ret != 0)
{
fprintf(stderr, "%s: %s\n", str, strerror(ret));
pthread_exit(NULL);
}
}
struct msg{
int num;
struct msg *next;
};
struct msg *head;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //定义并初始化一个互斥量
pthread_cond_t has_data = PTHREAD_COND_INITIALIZER; //定义并初始化一个条件变量
void *producer(void *arg)
{
while(1)
{
struct msg *mp = malloc(sizeof(struct msg));
mp->num = rand() % 1000 + 1;
printf("----produce %d\n", mp->num);
pthread_mutex_lock(&mutex);
mp->next = head; //写公共区域(生产)
head = mp;
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&has_data); //唤醒阻塞在条件变量has_data上的线程
sleep(rand() % 3);
}
return NULL;
}
void *consumer(void *arg)
{
while(1)
{
struct msg *mp;
pthread_mutex_lock(&mutex); //加锁
while(head == NULL) //当又多个消费者时,应该用while而不是if
{
pthread_cond_wait(&has_data, &mutex); //阻塞等待条件变量
}
mp = head;
head = mp->next;
pthread_mutex_unlock(&mutex);
printf("consume id: %lu, %d\n",pthread_self(), mp->num);
free(mp);
sleep(rand() % 3);
}
return NULL;
}
int main(int argc, char *argv[])
{
int ret;
pthread_t pid, cid;
srand(time(NULL));
ret = pthread_create(&pid, NULL, producer, NULL); //producer thread
err_thread(ret, "producer pthread_create error");
ret = pthread_create(&cid, NULL, consumer, NULL); //consumer thread
err_thread(ret, "consumer pthread_create error");
ret = pthread_create(&cid, NULL, consumer, NULL); //consumer thread
err_thread(ret, "consumer pthread_create error");
ret = pthread_create(&cid, NULL, consumer, NULL); //consumer thread
err_thread(ret, "consumer pthread_create error");
pthread_join(pid, NULL);
pthread_join(cid, NULL);
return 0;
}
参考资料:
条件变量_百度百科