条件变量:
本身不是锁! 但是通常结合锁来使用。 mutex
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(): 唤醒阻塞在条件变量上的 所有线程。
【要求,能够借助条件变量,完成生成者消费者】
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.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 = NULL;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 定义/初始化一个互斥量
pthread_cond_t has_data = PTHREAD_COND_INITIALIZER; // 定义/初始化一个条件变量
void *produser(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) {
pthread_cond_wait(&has_data, &mutex); // 阻塞等待条件变量, 解锁
} // pthread_cond_wait 返回时, 重新加锁 mutex
mp = head;
head = mp->next;
pthread_mutex_unlock(&mutex); // 解锁 互斥量
printf("---------consumer 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, produser, NULL); // 生产者
if (ret != 0)
err_thread(ret, "pthread_create produser error");
ret = pthread_create(&cid, NULL, consumer, NULL); // 消费者
if (ret != 0)
err_thread(ret, "pthread_create consuer error");
ret = pthread_create(&cid, NULL, consumer, NULL); // 消费者
if (ret != 0)
err_thread(ret, "pthread_create consuer error");
ret = pthread_create(&cid, NULL, consumer, NULL); // 消费者
if (ret != 0)
err_thread(ret, "pthread_create consuer error");
pthread_join(pid, NULL);
pthread_join(cid, NULL);
return 0;
}