条件变量是用来等待而不是用来上锁的,条件变量本身不是锁。条件变量和互斥锁同时使用。
条件变量的两个动作: 条件不满, 阻塞线程 当条件满足, 通知阻塞的线程开始工作。
条件变量的类型: pthread_cond_t。
1、条件变量初始化
#include<pthread.h>
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);使用静态初始化的方法,初始化条件变量:
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
功能:
初始化一个条件变量
参数:
cond:指向要初始化的条件变量指针。attr:条件变量属性,通常为默认值,传NULL即可
返回值:
成功:0
失败:非0错误号
2、释放条件变量
#include<pthread.h>
int pthread_cond_destroy(pthread_cond_t *cond);
功能:
销毁一个条件变量
参数:
cond:指向要初始化的条件变量指针
返回值:
成功:0
失败:非0错误号
3、等待条件
#include<pthread.h>
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
功能:
阻塞等待一个条件变量先解锁、等待条件满足、重新上锁(3步为原子操作)解阻塞
参数:
cond:指向要初始化的条件变量指针
mutex:互斥锁
返回值:
成功:0
失败:非0错误号
int pthread_cond_timedwait(pthread_cond_t *cond,pthread_mutex_t *mutex,
const struct *abstime);
功能:
限时等待一个条件变量
参数:
cond:指向要初始化的条件变量指针mutex:互斥锁
abstime:绝对时间
返回值:
成功:0
失败:非0错误号
4、唤醒等待在条件变量上的线程
#include<pthread.h>
int pthread_cond_signal(pthread_cond_t *cond);
功能:
唤醒至少一个阻塞在条件变量上的线程
参数
cond:指向要初始化的条件变量指
返回值
成功:0
失败:非0错误号
int pthread_cond_broadcast(pthread_cond_t* cond);
功能:
唤醒全部阻塞在条件变量上的线程
参数:
cond:指向要初始化的条件变量指针
返回值:
成功:0
失败:非0错误号
示例代码 生产者消费者
#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;
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;
}
网友评论