概述
条件变量不是一个把锁,它实质上一个类似信号的东西,与锁相互配合使用,因为锁所能达到的功能就只有加锁和解锁,并不能实现线程之间的一些关联,于是条件变量就出现了,与锁相互配合使用。这与共享内存与信号量配合使用有些许相似之处。
注意
进程中有两个线程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$
往期 · 推荐