多线程的互斥与同步:条件变量

用条件变量结合互斥锁来实现互斥和同步的大致过程:一个线程用pthread_cond_wait()函数将自己插入到条件变量的等待队列里,等待其他线程用pthread_cond_signal()或pthread_cond_broadcast()来唤醒自己,从而实现对临界资源的互斥和同步访问。

将线程自己插入到条件变量的等待队列中:
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);

唤醒在等待队列中的线程:
int pthread_cond_signal(pthread_cond_t *cond); //只唤醒一个等待的线程
int pthread_cond_broadcast(pthread_cond_t *cond); //唤醒全部等待的线程

test: 创建一个写线程来对临界资源写操作,一个读线程来读临界资源,确保在写线程
写完临界资源后,读线程才能读临界资源。

include <stdio.h>
#include <pthread.h>
#include <unistd.h>

pthread_cond_t cond;    //条件变量
pthread_mutex_t mutex;  //互斥锁
int wait = 0;   //判断条件(共享资源)
int global = 0; //共享资源

void *thread_write(void *arg)
{
    for(int i = 0; i < 4; ++i)
    {
        sleep(1);
        pthread_mutex_lock(&mutex); //上锁访问共享资源

        global++;   //写线程修改数据
        printf("thread_write have changed shared global\n");

        while(wait == 0)    //判断读线程是否准备好读写数据化
        {
            pthread_mutex_unlock(&mutex);   //释放锁,休眠1s,判断读线程是否准备好
            sleep(1);   

            pthread_mutex_lock(&mutex); //继续上锁,判断wait是否
        }

        pthread_mutex_unlock(&mutex);
        //循环结束,即表示读线程已经准备好了
        //用pthread_cond_signal或者pthread_cond_broadcast来唤醒条件变量的等待队列里的线程

        pthread_cond_broadcast(&cond);  //以广播的形式唤醒等待队列里所有的阻塞线程
    }
}

void *thread_read(void *arg)
{
     for(int i = 0; i < 4; ++i)
     {
        pthread_mutex_lock(&mutex); //上锁,访问共享资源
        sleep(1);
        wait = 1;   //将判断条件置为1,代表读线程已经准备好
        printf("thread_read is ready...\n");
        //将读线程加入到条件变量的等待队列里
        pthread_cond_wait(&cond, &mutex);   
		//读线程访问临界资源
        printf("thread_read read global = %d\n", global);   
        wait = 0;

        pthread_mutex_unlock(&mutex);

     }   
}
int main(int argc, char const *argv[])
{
    //初始化互斥锁和条件变量
    pthread_mutex_init(&mutex, NULL);
    pthread_cond_init(&cond, NULL);

    pthread_t tid[2];
    pthread_create(&tid[0], NULL, thread_write, NULL);
    pthread_create(&tid[1], NULL, thread_read, NULL);

    pthread_join(tid[0], NULL);
    pthread_join(tid[1], NULL);

    //销毁互斥锁和条件变量
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);

    return 0;
}

在这里插入图片描述

结果分析:
(1)如果thread_read先执行,在更改了判断条件wait后,表明读线程已经准备好读,就将自己插入到条件变量的等待队列里,等待thread_write来唤醒
(2)thread_write先执行,先上锁,然后更改临界资源后,在while循环里判断读线程是否准备好,如果循环结束,即代表读线程已经被准好读,那么将用broadcast来唤醒处于等待队列里的读线程。
这样就既保证了两个线程对临界资源的互斥访问,又实现了两个线程之间的同步(即必须在写线程修改临界资源后,读线程才能访问临界资源)。

将线程加入到条件变量的等待队列,阻塞、解除阻塞的大致过程:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值