概述
条件变量不是一个把锁,它实质上一个类似信号的东西,与锁相互配合使用,因为锁所能达到的功能就只有加锁和解锁,并不能实现线程之间的一些关联,于是条件变量就出现了,与锁相互配合使用。这与共享内存与信号量配合使用有些许相似之处。
注意
进程中有两个线程A和B,线程A由于某个条件不满足,阻塞等待条件为真,线程B执行的时候,使线程A等待的条件变为真。线程A继续执行,那么这个条件就是条件变量类型的一个变量。
另外,小编所有文章均是自己亲手编写验证,由于文件太多,小编就不在公众号后台一一回复列举了,若需要小编的工程代码,请关注公众号:不只会拍照的程序猿,后台回复需要的工程文件。小编看到后会第一时间回复。
接口
初始化条件变量
静态初始化
/**
* @ 静态初始化一个条件变量
*/
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
动态初始化
/**
* @ 动态初始化一个条件变量
* @ cond: 指定要初始化的条件变量的地址 cond_attr: NULL 默认值
* @ 总是成功返回0
*/
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
销毁条件变量
/**
* @ 销毁条件变量,释放条件变量hold的资源
* @ cond: 指定要销毁的条件变量的地址
* @ 成功返回0,失败返回非0的错误码
*/
int pthread_cond_destroy(pthread_cond_t *cond);
启动等待线程
重启一个线程
/**
* @ 从等待条件变量为真的线程中,重新启动一个线程,不确定哪一个.如果没有线程等待条件变量为真,什么都没发生
* @ cond: 指定条件变量.在这个条件变量上等待的线程
* @ 成功返回0,失败返回非0的错误码
*/
int pthread_cond_signal(pthread_cond_t *cond);
重启所有线程
/**
* @ 重新启动等待条件变量为真的所有线程.如果没有线程阻塞,什么都不做
* @ cond: 指定条件变量.在这个条件变量上等待的线程
* @ 成功返回0,失败返回非0的错误码
*/
int pthread_cond_broadcast(pthread_cond_t *cond);
等待条件变量为真
阻塞等待
/**
* @ 阻塞等待条件变为真
* @ cond:指定条件变量 mutex: 指定锁的地址
* @ 成功返回0,失败返回非0的错误码
*/
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
计时等待
/**
* @ 计时等待条件变量为真
* @ cond:条件变量 mutex: 指定锁的地址 abstime:计时时间
* @ 成功返回0,失败返回非0的错误码
*/
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime);
示例
★示例通过cond_test.c向用户展示条件变量的基本使用。
★包含演示程序cond_test.c(已验证通过)。
cond_test.c
/**
* @Filename : cond_test.c
* @Revision : $Revision: 1.00 $
* @Author : Feng(更多编程相关的知识和源码见微信公众号:不只会拍照的程序猿,欢迎订阅)
* @Description : 条件变量的基本应用示例
**/
#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
/* 定义链表相关类型 */
struct node;
typedef struct node *list_t;
struct node {
int data;
struct node *next;
};
list_t head = NULL; /* 链表初始化 */
/* 静态初始化锁 */
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
/* 静态初始化一个条件变量 */
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
/**
* @ 生产者线程
* @ args: 传递来的参数
*/
void *product(void *arg)
{
struct node *tmp;
while (1) {
//生产一个新的节点
tmp = (list_t)malloc(sizeof(struct node));
tmp->data = rand()%1000+1;
tmp->next = NULL;
printf("p:%d\n",tmp->data);
pthread_mutex_lock(&mutex); /* 加锁 */
/* 将新节点插入到链表的头部 */
tmp->next = head;
head = tmp;
pthread_mutex_unlock(&mutex); /* 解锁 */
pthread_cond_signal(&cond); /* 发送条件变量 */
sleep(rand()%5+1);
}
}
/**
* @ 消费者线程
* @ args: 传递来的参数
*/
void *consume(void *arg)
{
list_t tmp;
while (1) {
pthread_mutex_lock(&mutex); /* 加锁 */
if (head == NULL)
pthread_cond_wait(&cond,&mutex); /* 阻塞等待生产者生产//解锁 等待 重新获取锁 */
tmp = head;
head = head->next;
pthread_mutex_unlock(&mutex); /* 解锁 */
printf("c:%d\n",tmp->data); /* 消费tmp */
free(tmp);
tmp = NULL;
sleep(rand()%5+1);
}
}
/**
* @ 主函数,程序入口
*/
int main(void)
{
pthread_t pid, cid; /* 线程ID */
srand(time(NULL));
/* 创建线程 */
if (pthread_create(&pid, NULL, product, "thread1") != 0) {
printf("pthread1 create failed...\n");
return -1;
}
if (pthread_create(&cid, NULL, consume, "thread2") != 0) {
printf("pthread2 create failed...\n");
return -1;
}
/* 阻塞等待线程的汇合,接收线程的退出状态码 */
pthread_join(pid, NULL);
pthread_join(cid, NULL);
/* 销毁mutex锁 */
pthread_mutex_destroy(&mutex);
/* 销毁条件变量 */
pthread_cond_destroy(&cond);
return 0;
}
验证
编译程序,记得加库-pthread
#编译代码,记得-pthread
ubuntu@U:~/study/cond$ gcc cond_test.c -pthread
ubuntu@U:~/study/cond$
执行程序
#执行代码
ubuntu@U:~/study/cond$ ./a.out
p:99
c:99
p:417
c:417
^C
ubuntu@U:~/study/cond$
往期 · 推荐
实时系统vxWorks - 任务(重要)
实时系统vxWorks - 加载应用程序的方法
实时系统vxWorks - 在线调试
实时系统vxWorks - 虚拟机环境搭建
实时系统vxWorks - zynq7020移植vxWorks