动图–一个在打印里去掉了延时:
解析–提前看一下
两个线程的锁、解锁等操作,是同时进行的
进入线程, 1、 2开始抢资源
1、
1 抢到, 进入资源,那 2 就会阻塞住
然后打印"hello", 接着 1 线程开始解锁, /2 线程同步的会进入资源,上锁开始执行操作
2 线程会迅速的进入资源,并且上锁 ,为了防止 2 线程会立刻打印"world"
我们为 2 线程 添加一个【条件变量】的阻塞,让它停在(阻塞)在执行【my_print】的外面
2、
2 线程进入资源后, 会遇到 【条件变量】,它打开锁, 但是会阻塞在那里
此时 1线程,会执行【条件变量】broadcast函数, 对 2 线程中 的条件阻塞,发送唤醒指令
/*✳✳✳✳✳同时因为【条件变量】broadcast函数具有对【条件变量】解除阻塞 ‘+’ 【mutex】上锁的能力✳✳✳✳✳*/
所以 2 线程中的【条件变量】阻塞 函数, 会在接触阻塞的同时, 对【mutex】上锁
然后 2 线程放开阻塞, 进入 执行"world",
执行完"world", 2 线程会立刻 解锁 === 1 线程立刻进入资源且上锁
1、
1 线程开始立刻执行,然后解锁,
那么此时, 上锁的 【条件变量】阻塞 函数就会防止 ,执行完 1 执行完, 立马执行 2 线程
只有在 1 线程执行到 发送解除阻塞、唤醒函数的时候, 2 线程才会进去执行
代码–两个线程中都必须添加延时:
#if 1 // ---------------- 2个线程 ------1个条件变量 -----//
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include <pthread.h>
#include <string.h>
pthread_mutex_t mutex;//= PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond;//条件变量
void my_print(char *str)
{
//printf("%s\n", str);
while (*str != '\0')
{
putchar(*str);
fflush(stdout);
str++;
//sleep(1);//--可以不去
}
printf("\n");
}
void *callback_1(void *arg)
{
//lock 尝试加锁,如果加锁不成功,线程阻塞,阻塞到持有该互斥量的其他线程【解锁】为止!!!
//unlock 主动解锁函数,同时将阻塞在该锁上的所有线程全部唤醒,至于哪个线程先被唤醒,取决于优先级、调度。
//默认:先阻塞、先唤醒。
int i = 0;
for(; i < 3; i++)
{
//加锁: --操作, 阻塞线程
//上锁-可理解为将mutex–(或 -1),操作后mutex 的值为 0
pthread_mutex_lock(&mutex); //1.1
pthread_cond_wait(&cond, &mutex); //2.2//阻塞该任务,且打开锁,解除任务1的阻塞
my_print("world"); //3.1
//sleep(1);
//解锁: ++操作, 换醒阻塞在锁上的线程
//解锁-可理解为将mutex ++(或 +1),操作后mutex 的值为 1。
pthread_mutex_unlock(&mutex);
sleep(1);//延时一下,给线程 1 进入资源时间
}
}
void *callback(void *arg)
{
int i = 0;
for(; i < 3; i++)
{
pthread_mutex_lock(&mutex); //1.
my_print("hello");
pthread_mutex_unlock(&mutex); //2.
sleep(1);//用来缓冲上锁、解锁时间
pthread_cond_broadcast(&cond); //3.解除所有在条件变量cond上的阻塞,同时上锁
sleep(1);//用来缓冲上锁、解锁时间
}
}
//两个线程的锁、解锁等操作,是同时进行的
//进入线程, 1、 2开始抢资源
// 1、
// 1 抢到, 进入资源,那 2 就会阻塞住
//然后打印"hello", 接着 1 线程开始解锁, /2 线程同步的会进入资源,上锁开始执行操作
//2 线程会迅速的进入资源,并且上锁 ,为了防止 2 线程会立刻打印"world"
//我们为 2 线程 添加一个【条件变量】的阻塞,让它停在(阻塞)在执行【my_print】的外面
// 2、
//2 线程进入资源后, 会遇到 【条件变量】,它打开锁, 但是会阻塞在那里
//此时 1线程,会执行【条件变量】broadcast函数, 对 2 线程中 的条件阻塞,发送唤醒指令
/*✳✳✳✳✳同时因为【条件变量】broadcast函数具有对【条件变量】解除阻塞 ‘+’ 【mutex】上锁的能力✳✳✳✳✳*/
//所以 2 线程中的【条件变量】阻塞 函数, 会在接触阻塞的同时, 对【mutex】上锁
//然后 2 线程放开阻塞, 进入 执行"world",
//执行完"world", 2 线程会立刻 解锁 === 1 线程立刻进入资源且上锁
//1、
//1 线程开始立刻执行,然后解锁,
//那么此时, 上锁的 【条件变量】阻塞 函数就会防止 ,执行完 1 执行完, 立马执行 2 线程
//只有在 1 线程执行到 发送解除阻塞、唤醒函数的时候, 2 线程才会进去执行
int main()
{
pthread_cond_init(&cond, NULL);
int ret = pthread_mutex_init(&mutex, NULL);//申请动态锁。局部变量应采用动态初始化,正常返回【 0 】
if(ret != 0)
{
fprintf(stderr,"mute init error:%d\n", ret);
exit(1);
}
pthread_t pth, pth1;
pthread_create(&pth,NULL, callback, NULL);//线程的创建
pthread_create(&pth1,NULL, callback_1, NULL);
pthread_join(pth, NULL);//线程等待回收(带阻塞)
pthread_join(pth1, NULL);
pthread_mutex_destroy(&mutex);//销毁互斥锁
pthread_cond_destroy(&cond);
return 0;
}
#endif