Linux 同步:条件变量

我们知道互斥是为了保证每次只能有一个执行流访问临界资源。接下来我们看看为什么还需要同步?

同步

同步是为了保证执行流访问临界资源的合理性。 也就是说当没有临界资源了,让执行流(消费者)进行等待,等待另一个执行流(生产者)来生产一个临界资源,之后再唤醒刚才进入等待的执行流进行访问资源。

举个例子现在有一个全局变量g_val=0,但是有一个执行流A想对g_val进行-1操作,因为临界资源此时为0,所以让A先进入等待,直到另一个执行流B对临界资源g_val进行+1操作,此时临界资源g_val为1,B才能唤醒A去拿互斥锁,对g_val进行操作。

那么同步是怎么实现的呢?这就必须用到条件变量

条件变量

条件变量提供了两个接口(等待接口、唤醒接口)和一个PCB等待队列
条件变量的接口:
1.定义条件变量:
pthread_cond_t con;
2.条件变量初始化:
(1)pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *attr);
cond:传入条件变量的地址。
attr:传入条件变量的属性,通常传入NULL,默认属性。
(2)pthread_cond_t con=PTHREAD_COND_INITIALIZER;
3.等待接口:
pthread_cond_wait (pthread_cond_t *cond,pthread_mutex_t *mutex);
cond:传入条件变量的地址。
mutex:传入互斥锁变量的地址。

这里大家可能有疑问了,条件变量是实现同步的,那么为什么要用到互斥变量呢?
因为条件变量只保证了同步,但是各个执行流之间的冲突还是存在的,也是有可能造成程序的二义性。
举个例子来理解一下:
若此时临界资源g_val为0,那么当有消费线程访问g_val发现没有可用资源,就会调用等待接口把PCB放到等待队列中等待生产线程生产g_val。如果生产了一个资源,此时就会唤醒等待队列中的消费线程来消费,因为等待的不止一个线程,所以这些线程被唤醒时,不可能同时访问g_val,还是需要先获取互斥锁,才能访问g_val。

那么问题又来了,这个等待接口中是如何使用互斥锁的呢?
当线程调用了等待接口后,此时调用接口的线程陷入阻塞状态。
等待接口内部操作分为三步:
(1)将线程PCB放到PCB等待队列中去。
(2)释放互斥锁。
(3)被生产线程从PCB等待队列中唤醒,争夺锁资源。争夺到了访问临界资源,否则无法访问临界资源,继续调用等待接口。

4.唤醒接口
pthread_cond_signal(pthread_cond_t* cond);
cond:传入条件变量的地址。
唤醒PCB等待队列至少一个等待线程

pthread_cond_broadcast(pthread_cond_t* cond);
唤醒PCB等待队列里的全部等待线程。

5.摧毁条件变量
pthread_cond_destroy(pthread_cond_t* cond)

同步的实现代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值