109_多线程_另一种同步条件变量+互斥锁【这里可以完成同步,但是注意:线程的执行顺序是同时进行的,所以对其中个别操作添加延时,以让部分步骤充分响应】【条件变量的broadcast、wait】

动图–一个在打印里去掉了延时:

109_多线程_另一种同步条件变量+互斥锁【这里可以完成同步,但是注意:线程的执行顺序是同时进行的,所以对其中个别操作添加延时,以让部分步骤充分响应】【条件变量的broadcast、wait】
109_多线程_另一种同步条件变量+互斥锁【这里可以完成同步,但是注意:线程的执行顺序是同时进行的,所以对其中个别操作添加延时,以让部分步骤充分响应】【条件变量的broadcast、wait】

解析–提前看一下

两个线程的锁、解锁等操作,是同时进行的

进入线程, 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

上一篇:Linux中的线程


下一篇:仅使用互斥锁实现读写锁