【转】pthread_cond_signal 虚假唤醒问题

引用:http://blog.csdn.net/leeds1993/article/details/52738845

什么是虚假唤醒?

举个例子,我们现在有一个生产者-消费者队列和三个线程。

I.1号线程从队列中获取了一个元素,此时队列变为空。 
II.2号线程也想从队列中获取一个元素,但此时队列为空,2号线程便只能进入阻塞(cond.wait()),等待队列非空。 
III.这时,3号线程将一个元素入队,并调用cond.notify()唤醒条件变量。 
IV.处于等待状态的2号线程接收到3号线程的唤醒信号,便准备解除阻塞状态,执行接下来的任务(获取队列中的元素)。 
V.然而可能出现这样的情况:当2号线程准备获得队列的锁,去获取队列中的元素时,此时1号线程刚好执行完之前的元素操作,返回再去请求队列中的元素,1号线程便获得队列的锁,检查到队列非空,就获取到了3号线程刚刚入队的元素,然后释放队列锁。 
VI.等到2号线程获得队列锁,判断发现队列仍为空,1号线程“偷走了”这个元素,所以对于2号线程而言,这次唤醒就是“虚假”的,它需要再次等待队列非空。

使用while()判断的原因

在多核处理器下,pthread_cond_signal可能会激活多于一个线程(阻塞在条件变量上的线程)。结果就是,当一个线程调用pthread_cond_signal()后,多个调用pthread_cond_wait()或pthread_cond_timedwait()的线程返回。这种效应就称为“虚假唤醒”。

注:pthread_cond_wait这个函数是单个原子操作,即这个函数的两个动作:解锁 && 进入block 是一个原子操作。

时间: 2024-10-18 05:24:06

【转】pthread_cond_signal 虚假唤醒问题的相关文章

多线程编程中条件变量和的spurious wakeup 虚假唤醒

1. 概述 条件变量(condition variable)是利用共享的变量进行线程之间同步的一种机制.典型的场景包括生产者-消费者模型,线程池实现等. 对条件变量的使用包括两个动作: 1) 线程等待某个条件, 条件为真则继续执行,条件为假则将自己挂起(避免busy wait,节省CPU资源): 2) 线程执行某些处理之后,条件成立:则通知等待该条件的线程继续执行. 3) 为了防止race-condition,条件变量总是和互斥锁变量mutex结合在一起使用. 一般的编程模式: C++代码  

什么是虚假唤醒 spurious wakeup

解释一下什么是虚假唤醒? 说具体的例子,比较容易说通. pthread_mutex_t lock; pthread_cond_t notempty; pthread_cond_t notfull; void *producer(void *data){ for(int i = 0;i<=16;i++){ pthread_mtext_lock(&lock); while(buffer if full){ pthread_cond_wait(&notfull, &lock); }

java多线程 生产者消费者案例-虚假唤醒

package com.java.juc; public class TestProductAndConsumer { public static void main(String[] args) { Clerk clerk = new Clerk(); Produce produce = new Produce(clerk); Consumer consumer = new Consumer(clerk); new Thread(produce, "线程A").start(); ne

【转】通过生产者消费者案例理解等待唤醒机制和虚假唤醒

首先引入下面这段生产者和消费者的程序,店员类作为生产产品和消费产品的中介,其中的数据product为共享数据,产品最多只能囤积5个,当产品达到5个还在生产时,就会提示"产品已满!",类似地,如果产品只有0个了还在消费,会提示"缺货!": 1 package concurrent; 2 3 //店员类 4 class Clerk { 5 private int product = 0; 6 7 // 进货 8 public synchronized void get(

(三)juc高级特性——虚假唤醒 / Condition / 按序交替 / ReadWriteLock / 线程八锁

8. 生产者消费者案例-虚假唤醒 参考下面生产者消费者案例: /* * 生产者和消费者案例 */ public class TestProductorAndConsumer { public static void main(String[] args) { Clerk clerk = new Clerk(); Productor pro = new Productor(clerk); Consumer cus = new Consumer(clerk); new Thread(pro, "生产

生产者消费者和虚假唤醒

1 定义 虚假唤醒,即spurious wakeups.wait需要在while循环内使用,原因就是因为存在虚假唤醒. 2 Monitor 还是放上这个神图来复习下线程间通信 线程在竞争锁失败的情况下会放到Entry Set中,图中2表示线程可以获取锁 获取到锁的线程可以调用wait方法,让线程阻塞,此时线程被放到了Wait Set中,如图中3所示:Wait Set中的线程在时间到或者被notify后可以竞争锁,如图中4所示 Wait Set中的线程在获取到锁后才可以继续执行. notify会唤

生产者与消费者案例-虚假唤醒

以下是一个案例,有一个店员,负责进货和卖货.进货生产,卖货消费. 当商品超过10件,生产等待,消费继续,当少于0件,消费等待,消费继续. 正常代码如下: package com.atguigu.juc; /* * 生产者和消费者案例 */ public class TestProductorAndConsumer { public static void main(String[] args) { Clerk clerk = new Clerk(); Productor pro = new Pr

pthread_cond_wait虚假唤醒

pthread_cond_wait中的while()不仅仅在等待条件变量前检查条件cond_is_false是否成立,实际上在等待条件变量后也检查条件cond_is_false是否成立.在多线程等待的情况下,这样对condition进行多做一次判断,即可避免"虚假唤醒". pthread_mutex_lock(&mutex); while(cond_is_false) pthread_cond_wait(&cond, &mutex); pthread_mutex

wait notify之虚假唤醒

虚假唤醒的概念 jdk官方文档解释: 所以说在wait和notify一块使用时,如果使用if作为条件时,会有虚假唤醒的情况发生,所以必须使用while作为循环条件.下面来举例实验: 首先,创建一个资源类:(在多线程中,一般都是资源类和线程操作解耦,不放在用同一个类中,只有在线程操作资源类时,才会创建资源类的对象) package com.test; /** * 资源类 * @author Huxudong * @createTime 2020-04-01 21:57:39 **/public c