目录
基本理解
- 条件变量是用于线程同步,关注对象是共享数据状态的变化,用来协调各个线程合作完成某个任务。当一个动作需要另外一个动作完成时才能进行时,即:当一个线程的行为依赖于另外一个线程对共享数据状态的改变时,这时候就可以使用条件变量。
- 条件变量是与互斥量相关联的一种用于多线程之间关于共享数据状态改变的通信机制。
- 条件变量与互斥量一起使用的时候,允许线程以无竞争的方式等待特定的条件发生。
- 条件变量是由互斥量保护的,线程在改变条件变量状态前必须先锁住互斥量。
- 互斥锁是用来防止对变量的破坏,即规范线程对共享数据的竞争使用;
- 互斥锁的特点是资源的”无序访问“。
- 互斥锁及互斥属性块的操作见:https://blog.csdn.net/Liangren_/article/details/116052864
pthread_cond_wait() 执行时内部会解锁互斥锁,然后等待条件变量被其他线程激活,被激活后会再自动加锁(在其他线程释放互斥锁之后),并重新判断条件变量阻塞条件是否成立,成立重新挂起,不成立则继续往下执行。
线程调用pthread_cond_wait() 这个函数之后,内核会做下面这些事:
1,拿到锁的线程,把锁暂时释放;
2,线程休眠,进行等待;
3,线程等待通知,要醒来。(重新获取锁)
线程库将上面三步做成了原子性操作;
代码实现
思路:使用信号量cond和互斥锁lock,创建两个同优先级线程 thread_a, thread_b 均使用互斥锁完成资源互斥访问,thread_a 以条件变量作为等待条件,thread_b 完成条件变量的释放,具体代码实现如下,为方便查看程序运行过程,代码内部添加了几处标记打印。
#include <stdio.h>
#include <pthread.h>
/*********************************************************************************************************
全局变量定义
*********************************************************************************************************/
static pthread_mutex_t lock;
static pthread_cond_t cond;
static int count = 0;
/*********************************************************************************************************
** 函数名称: thread_a
** 功能描述: 线程函数
** 输 入 : arg 传入的参数
** 输 出 : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
static void *thread_a (void *arg)
{
while (1) {
pthread_mutex_lock(&lock);//1 getlock
printf("thread_a()1: count = %d\n", count);
pthread_cond_wait(&cond, &lock);//2 postlock,waitcond //6 getcond, getlock
printf("thread_a()2: count = %d\n", count);
pthread_mutex_unlock(&lock);//7 postlock
}
return (NULL);
}
/*********************************************************************************************************
** 函数名称: thread_b
** 功能描述: 线程函数
** 输 入 : arg 传入的参数
** 输 出 : NONE
** 全局变量:
** 调用模块:
*********************************************************************************************************/
static void *thread_b (void *arg)
{
while (1) {
pthread_mutex_lock(&lock);//3 getlock
count++;
printf("thread_b()1: count = %d\n", count);
pthread_cond_broadcast(&cond);//4 postcond
printf("thread_b()2: count = %d\n", count);
pthread_mutex_unlock(&lock);//5 postlock
sleep(1);//确保 thread_b 释放互斥锁后 thread_a 可以获得锁资源,否则 thread_b 将一直持有锁
}
return (NULL);
}
/*********************************************************************************************************
** 函数名称: main
** 功能描述: 主函数
** 输 入 : argc,argv
** 输 出 : ERROR
** 全局变量:
** 调用模块:
*********************************************************************************************************/
int main (int argc, char *argv[])
{
pthread_t threada_tid;
pthread_t threadb_tid;
int ret;
ret = pthread_mutex_init(&lock, NULL);
if (ret != 0) {
fprintf(stderr, "mutex create failed.\n");
return (-1);
}
ret = pthread_cond_init(&cond, NULL);
if (ret != 0) {
fprintf(stderr, "cond create failed.\n");
return (-1);
}
ret = pthread_create(&threada_tid, NULL, thread_a, NULL);
if (ret != 0) {
fprintf(stderr, "pthread create failed.\n");
return (-1);
}
ret = pthread_create(&threadb_tid, NULL, thread_b, NULL);
if (ret != 0) {
fprintf(stderr, "pthread create failed.\n");
return (-1);
}
pthread_join(threada_tid, NULL);
pthread_join(threadb_tid, NULL);
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&lock);
return (0);
}
逻辑分析
先上程序运行结果吧:
程序运行的逻辑分析我根据个人理解画了个图,关于两个线程内代码的运行顺序我已经加在上方代码的注释里面了,可以查看参考。