论条件变量cond_wait的原子性

使用的基本模板如下(参考APUE):

signal代码序列如下,

pthread_mutex_lock

...

pthread_cond_signal

pthread_mutex_unlock

wait代码序列如下,

while (1){
pthread_mutex_lock(&mutex);
while(iCount < 100){
pthread_cond_wait(&cond, &mutex);
}
printf("iCount >= 100\r\n");
iCount = 0;
pthread_mutex_unlock(&mutex);
}

小小几行代码,背后有大学问,这里就把几点重要的地方阐明一下,

首先,signal序列代码中,pthread_cond_signal和pthread_mutex_unlock可以对调,各有利弊参见APUE 11章习题4,以及百度百科词条(pthread_cond_signal),两种写法各有利弊,linux下变成推荐本文开头的写法。

其次,我们始终假定,signal会通知到 不止一个线程。这里会涉及到调度问题,不再详述。

最后,cond_wait是原子的。phtread_cond_wait 的实现可以理解为如下几个步骤:

1 unlock mutex
2 sleep & wait for cond
3 cond ok & return
4 unlock mutex

解锁1和睡眠2是原子的,加锁3和唤醒4是原子的. 原子就是指线程在执行相关步骤时,不会被切换出去。如果不原子会有什么问题呢?

1~2  解锁和睡眠是原子的:lock --> 检查变量不满足 --> unlock --> sleep;如果变量的改变以及通知事件发生在unlock和sleep中间,那么你不会检测到,也就是错过了这次通知.
3~4  加锁和唤醒是原子的:wakeup -- > lock ----> 检查变量是否满足条件:如果在wakeup之后,在lock之前,其他线程可以修改数据,导致我们Lock后检查的数据可能与我们被唤醒的通知不是一个通知,也就是被1号通知唤醒,却检查了2号通知对变量的改变。

也就是说,如果1~2之间wait线程切出去了,那么他将因此损失一次本来可能属于自己的唤醒条件。

你也许会问,SMP条件下,两个线程同时运行,发出signal的线程和wait线程同时进行,1~2之间还是会发生可满足条件导致miss啊?但是,要明白,这个miss事件不是wait线程自己切换造成的,况且,在下次while判断时候,会接到这个提醒——如果,没有同事wait的其他线程的改变。同理,如果3~4之间发生事件(也是第三方线程知识),使本来可满足的条件变为不满足,则下次while循环也能判断出来。

假如有多个线程都在wait,那么wait的线程之间会影响彼此的判断,但是,这就是你允许多个wait的必须前提啊?!这还有神马可解释的呢!

论条件变量cond_wait的原子性

时间: 2024-10-10 10:40:54

论条件变量cond_wait的原子性的相关文章

深入解析条件变量(condition variables)

深入解析条件变量 什么是条件变量(condition variables) 引用APUE中的一句话: Condition variables are another synchronization mechanism available to threads. These synchronization objects provide a place for threads to rendezvous. When used with mutexes, condition variables al

详解条件变量

一年多过去啦,一段时间没有posix多线程的东西,又忘记的差不多略,我打记性咋这么差,丝毫记不起来怎么用啦,还是不如烂笔头啊. 大家都知道条件变量需要配合mutex一起使用,往往是这样的:lock->signal->unlock,  而另一边呢是: lock->wait->unlock. 在调用pthread_cond_wait(cond,mutex)时的执行顺序是这样的:1. 首先获取外面的mutex, 然后当前wait push 到一个等待的queue里面,然后释放锁.但是你看

Linux多线程实践(8) --Posix条件变量解决生产者消费者问题

Posix条件变量 int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr); int pthread_cond_destroy(pthread_cond_t *cond); int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); int pthread_cond_timedwait(pthread_cond_t *cond

操作系统思考 第十章 条件变量

第十章 条件变量 作者:Allen B. Downey 原文:Chapter 10 Condition variables 译者:飞龙 协议:CC BY-NC-SA 4.0 像上一章所展示的那样,许多简单的同步问题都可以用互斥体解决.这一章中我会介绍一个更大的挑战,著名的"生产者-消费者"问题,以及一个用于解决它的新工具,条件变量. 10.1 工作队列 在一些多线程的程序中,线程被组织用于执行不同的任务.通常它们使用队列来相互通信,其中一些线程叫做"生产者",向队列

浅析线程间通信一:互斥量和条件变量

线程同步的目的简单来讲就是保证数据的一致性.在Linux中,常用的线程同步方法有互斥量( mutex ).读写锁和条件变量,合理使用这三种方法可以保证数据的一致性,但值得的注意的是,在设计应用程序时,所有的线程都必须遵守相同的数据访问规则为前提,才能保证这些同步方法有效,如果允许某个线程在没有得到访问权限(比如锁)的情况下访问共享资源,那么其他线程在使用共享资源前都获得了锁,也会出现数据不一致的问题.另外还有自旋锁.barrier和信号量线程同步方法.本文将讨论互斥量和条件变量的使用,并给出了相

Linux多线程编程-条件变量

条件变量 如果说线程间的互斥锁是用来同步共享数据的访问的话,那么条件变量是用于线程之间共享数据的值.条件变量提供了一种线程之间的通知机制,当某个共享数据达到某个值时,唤醒等待这个共享数据的线程.条件变量相关函数主要 有5个: #include <pthread.h> int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr); int pthread_cond_destroy(pthread_

转: 【Java并发编程】之二十:并发新特性—Lock锁和条件变量(含代码)

简单使用Lock锁 Java5中引入了新的锁机制--Java.util.concurrent.locks中的显式的互斥锁:Lock接口,它提供了比synchronized更加广泛的锁定操作.Lock接口有3个实现它的类:ReentrantLock.ReetrantReadWriteLock.ReadLock和ReetrantReadWriteLock.WriteLock,即重入锁.读锁和写锁.lock必须被显式地创建.锁定和释放,为了可以使用更多的功能,一般用ReentrantLock为其实例化

条件变量(Condition Variable)详解

转载于:http://blog.csdn.net/erickhuang1989/article/details/8754357 条件变量(Condtion Variable)是在多线程程序中用来实现"等待->唤醒"逻辑常用的方法.举个简单的例子,应用程序A中包含两个线程t1和t2.t1需要在bool变量test_cond为true时才能继续执行,而test_cond的值是由t2来改变的,这种情况下,如何来写程序呢?可供选择的方案有两种: 第一种是t1定时的去轮询变量test_co

使用互斥量和条件变量实现线程同步控制

管程(monitor)说明 在并发编程中,管程(monitor)是一个同步构件,管程实现了同一时间点,最多只有一个线程可以执行管程的某个子程序.与那些通过修改数据结构实现互斥访问的并发程序设计相比,管程的实现很大程度上简化了程序设计. 管程可以确保一次只有一个进程执行管程中的程序,因此程序员不需要显式地编写同步代码,但是如果需要就某些特定条件上的同步,则需要定义一些条件结构(condition variable)来实现,并且对条件变量的操作仅有wait()和signal(),如下: condit