精华内容
下载资源
问答
  • 主要介绍了Java wait和notify虚假唤醒,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • pthread_cond_wait中有多个线程被阻塞时,没死pthread_cond_signal会唤醒一个线程,这个线程会先获取互斥锁之后再执行消费资源的逻辑(比如消息队列) 当wait里面有一个线程被唤醒时可能之后会获取互斥锁失败,因为互斥所...

    pthread_cond_wait中有多个线程被阻塞时,没死pthread_cond_signal会唤醒一个线程,这个线程会先获取互斥锁之后再执行消费资源的逻辑(比如消息队列)

    当wait里面有一个线程被唤醒时可能之后会获取互斥锁失败,因为互斥所肯能被其他未阻塞的线程提前获得. 当此线程获得互斥锁的时候资源可能被消耗了所以pthread_cond_wait外面需要一个while(x < y)这种逻辑包裹着

    pthread_mutex_lock(mutex)
    while (条件){
    pthread_cond_wait(&cond, &mutex);
    }
    pthread_mutex_unlock(mutex);


    pthread_cond_signal(&cond);

    展开全文
  • wait虚假唤醒

    2021-07-09 15:43:16
    //wait在哪里睡就在哪里醒,不能用if,需要用while class Share{ private int number = 0; public synchronized void incr() throws InterruptedException { while (number !=0){ this.wait(); } number++;...

    线程也可以唤醒,而不会被通知,中断或超时,即所谓的虚假唤醒 。 虽然这在实践中很少会发生,
    但应用程序必须通过测试应该使线程被唤醒的条件来防范,并且如果条件不满足则继续等待。
     换句话说,等待应该总是出现在循环中,就像这样:
    
      synchronized (obj) {
             while (<condition does not hold>)
                 obj.wait(timeout);
             ... // Perform action appropriate to condition
         } 
    
    
     //wait在哪里睡就在哪里醒,不能用if,需要用while
    class Share{
        private int number = 0;
    
        public synchronized void incr() throws InterruptedException {
    
            while (number !=0){
              this.wait();
            }
            number++;
            System.out.println(Thread.currentThread().getName()+"::"+number);
            this.notifyAll();
        }
    
        public synchronized void decr() throws InterruptedException {
    
            while (number !=1){
                this.wait(); //wait在哪里睡就在哪里醒,不能用if,需要用while
            }
            number--;
            System.out.println(Thread.currentThread().getName()+"::"+number);
            this.notifyAll();
        }
    }
    
    
    
    public class MainThreadDemo {
    
    
        public static void main(String[] args) {
    
    
            Share share = new Share();
            new Thread(()->{
                for(int i =1;i<=10;i++){
                    try {
                        share.incr();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"AA").start();
    
            new Thread(()->{
                for(int i =1;i<=10;i++){
                    try {
                        share.decr();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"BB").start();
    
    
            new Thread(()->{
                for(int i =1;i<=10;i++){
                    try {
                        share.incr();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"CC").start();
    
            new Thread(()->{
                for(int i =1;i<=10;i++){
                    try {
                        share.decr();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"DD").start();
    
    
    
    
    
        }
    }

    展开全文
  • 关于多线程下条件变量的作用这里就不多讲解了,这里主要是针对条件变量操作时需要注意一个特性虚假唤醒,首先看一段代码。 task * _deal_task = NULL; //lock pthread_mutex_lock(&m_thread_mutex); if...

    关于多线程下条件变量的作用这里就不多讲解了,这里主要是针对条件变量操作时需要注意一个特性虚假唤醒,首先看一段代码。

    	task * _deal_task = NULL;
    	//lock
    	pthread_mutex_lock(&m_thread_mutex);				
    
    	if(!m_task_queue.empty()) {
    		//get task
    		_deal_task = m_task_queue.front();
    		m_task_queue.pop();
    	}else{
    		printf("produce_consumer condition wait\n");
    		//deal spurious wakeup  - other singal affect this wait
    		while(m_task_queue.empty()) {
    			pthread_cond_wait(&m_thread_cond, &m_thread_mutex);
    			//if program recv stop  break this while
    			if(m_stop){
    				break;
    			}
    		}
    	}
    	//unlock
    	pthread_mutex_unlock(&m_thread_mutex);
    
    

    上述代码中可以发现在pthread_cond_wait上层有一层队列循环检测,目的就是为了处理虚假唤醒,因为我们用条件变量的时候等待cond信号,这个时候可能因为某些特殊条件,我们的cond_wait会被意外唤醒,所以我们需要再次对资源进行检测,确保是否达到所有触发的条件,如果没有满足条件我们则继续进行等待,如果满足就认为是正确的唤醒信号。

    展开全文
  • 在生产者和消费者问题中,使用wait()方法可能造成的虚假唤醒和解决方法 问题代码: public class A { public static void main(String[] args) { Data data = new Data(); new Thread(()->{ for (int i = 0; ...

    在生产者和消费者问题中,使用wait()方法可能造成的虚假唤醒和解决方法

    问题代码:

    public class A {
        public static void main(String[] args) {
            Data data = new Data();
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.increment();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"A").start();
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.decrement();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"B").start();
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.increment();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"C").start();
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.decrement();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"D").start();
        }
    }
    class Data{//判断等待
        private int number=0;
        //+1
        public synchronized void increment() throws InterruptedException {
            if (number!=0){
                //等待
                this.wait();
            }
            number++;
            System.out.println(Thread.currentThread().getName()+"->"+number);
            //通知其他线程,我+1完毕了
            this.notifyAll();
        }
    
        //-1
        public synchronized void decrement() throws InterruptedException {
            if (number==0){
                //等待
                this.wait();
            }
            number--;
            System.out.println(Thread.currentThread().getName()+"->"+number);
            //通知其他线程,我-1完毕了
            this.notifyAll();
        }
    }
    

    错误运行结果
    A->1
    B->0
    A->1
    B->0
    A->1
    B->0
    A->1
    B->0
    A->1
    B->0
    A->1
    B->0
    C->1
    A->2
    C->3
    B->2
    B->1
    B->0
    C->1
    A->2
    C->3
    B->2
    D->1
    D->0
    C->1
    A->2
    C->3
    D->2
    D->1
    C->2
    A->3
    C->4
    D->3
    D->2
    D->1
    D->0
    C->1
    D->0
    C->1
    D->0
    出现了不是0或1的数据。
    原因:
    判断number!=0和number==0时,使用了if进行判断,造成了虚假唤醒。
    解决方法:
    阅读JDK1.8的帮助文档
    Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).
    The current thread must own this object’s monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object’s monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.
    As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop:
    synchronized (obj) {
    while ()
    obj.wait();
    … // Perform action appropriate to condition
    }
    翻译内容:
    请添加图片描述
    所以不能使用if进行判断,应该使用while循环进行判断
    正确代码:

    public class A {
        public static void main(String[] args) {
            Data data = new Data();
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.increment();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"A").start();
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.decrement();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"B").start();
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.increment();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"C").start();
            new Thread(()->{
                for (int i = 0; i < 10; i++) {
                    try {
                        data.decrement();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            },"D").start();
        }
    }
    class Data{//判断等待
        private int number=0;
        //+1
        public synchronized void increment() throws InterruptedException {
            while (number!=0){
                //等待
                this.wait();
            }
            number++;
            System.out.println(Thread.currentThread().getName()+"->"+number);
            //通知其他线程,我+1完毕了
            this.notifyAll();
        }
    
        //-1
        public synchronized void decrement() throws InterruptedException {
            while (number==0){
                //等待
                this.wait();
            }
            number--;
            System.out.println(Thread.currentThread().getName()+"->"+number);
            //通知其他线程,我-1完毕了
            this.notifyAll();
        }
    }
    

    正确运行结果:
    A->1
    B->0
    A->1
    B->0
    A->1
    B->0
    A->1
    B->0
    C->1
    B->0
    A->1
    B->0
    C->1
    B->0
    A->1
    B->0
    C->1
    B->0
    A->1
    D->0
    C->1
    B->0
    A->1
    D->0
    C->1
    D->0
    A->1
    D->0
    C->1
    D->0
    A->1
    D->0
    C->1
    D->0
    C->1
    D->0
    C->1
    D->0
    C->1
    D->0
    问题解决!

    展开全文
  • wait()-虚假唤醒

    2020-09-22 08:34:08
    } } private void consume() { synchronized (lock) { if (product ) { try { lock.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } product = product - 1...
  • Object wait():使一个线程处于等待状态,释放CPU和锁资源 Causes the current thread to wait until either another thread invokes The current thread must own this object's monitor. // 否则: ...
  • 总:我发现其实网上好多人在解释 线程间通信--问题:虚假唤醒的时候都是说错了的,下面谈谈自己的理解!!!!! 案例:一个资源类 中 +1和 -1 的2个同步方法,操作其属性 number; 首先应该明确:线程中使用wait()后...
  • 官方API明确的告诉我们,为了防止发生中断错误以及虚假唤醒的问题,我们需要将wait()方法放在while() 循环中使用 synchronized (obj) { while (&lt;condition does not hold&gt;) { obj.wait(); } ...
  • java在使用内置锁实现消费者-生产者模式的时候,可以使用wait,notify,notifyAll三个方法,而且这三个方法都是基类Object的方法,要调用某一个对象的同步方法时,必须将其放在sycronized修饰的方法、对象、代码块里面,你...
  • 条件变量之虚假唤醒

    千次阅读 2018-11-02 21:32:08
    当我们使用互斥量(Mutex)与条件变量(condition_variable)进行多线程同步时有可能会产生虚假唤醒现象, 那么究竟什么是虚假唤醒,它会在什么情况下被触发,什么情况下无需考虑虚假唤醒,如何避免? 1.什么是虚假...
  • 因为是10个消费者线程共同竞争数据,所以最终只有一个线程得到数据,另外9个线程被唤醒之后发现g_deque为空继续调用wait函数阻塞自己,这就导致了一个虚假唤醒的概念:明明当前线程已经被唤醒了,却得不到需要的数据...
  • 解决:根据wait的javadoc建议,将wait() 放在循环里进行操作即可,这样当两个消费者同时被唤醒时,就会再判定一次,从而不会产生虚假唤醒问题。 最后附上完整的代码 public class WatiTest { public static ...
  • 本文分享wait() 的虚假唤醒(Spurious Wakeups)问题,会说明什么是虚假唤醒,以及如何解决。先看一下相关的 java doc: java doc 说由于中断和虚假唤醒可能会发生,所以总是要在循环里面调用。由此可见解决办法其实很...
  • pthread_cond_wait()和pthread_cond_signal()的伪实现 pthread_cond_wait(mutex,cond) { // 保存条件变量的值 value = cond->value; // 解锁传入的已经锁住的互斥量 pthread_mutex_unlock(mutex); // 1 // ...
  • 虽然虚假唤醒在pthread_cond_wait函数中可以解决,为了发生概率很低的情况而降低边缘条件(fringe condition)效率是不值得的,纠正这个问题会降低对所有基于它的所有更高级的同步操作的并发度。所以pthread_cond_...
  • 也给出了建议的方法,用while代替if, 下次进入线程的时候在做一次判断,防止虚假唤醒;    2.第二种方式,用lock替带 synchronized;如下代码 public class ThreadDemo02 { public static void main...
  • 这里添加了一个while循环来处理虚假唤醒.boolean dosleep = true;while (dosleep){try {wait(2000);/*** Write some code here so that* if it is spurious wakeup, go back and sleep.* or if it is timeout...
  • pthread_cond_wait虚假唤醒 什么是虚假唤醒?简单说就是wait这个函数返回了,但是它等的那个条件并不满足。 为什么会这样? 有两种原因 这个条件从来就没有满足过,wiat函数的返回不是因为别的线程调用signal...
  • public class 虚假唤醒问题 { private static final Object room = new Object(); private static boolean hasCigarette = false; private static boolean hasTakeOut = false; public static void main(Str
  • } } 多个线程去操作同一资源时,则此时运行代码(多次运行),会出现以下问题: 多个线程造成的问题分析 在调用 java.lang.Object 类的 wait() 时,几率出现虚假唤醒的现象! 按照官方文档给出的建议,此时则需要修改...
  • 最近B站学习狂神的JUC并发编程时,听到了虚假唤醒这个词,虽然狂神进行了代码的演示,但我还是不太理解为什么使用if判断包装wait方法会出现虚假唤醒,查找了网上很多大佬的博客终于理解了,这里分享一下虚假唤醒产生...
  • Java虚假唤醒及如何避免虚假唤醒

    千次阅读 2021-01-13 10:50:08
    先给出一段虚假唤醒的代码如下: public class SynchronizeDemo2 { public static void main(String[] args) { Data2 data = new Data2(); new Thread(() -> { for (int i = 0; i < 5; i++) { try { ...
  • wait()方法虚假唤醒

    2021-08-27 19:31:20
    wait()写在if()循环中会产生虚假唤醒问题,可以用while替代if
  • C++11下条件变量之虚假唤醒

    千次阅读 2018-03-07 13:00:02
    其实,在条件变量中是可以实现杜绝虚假唤醒的,但是这样做会很大程度上影响条件变量的效率,因此将这个问题抛给了程序员。 另: 在进行条件变量的唤醒时我们通常有两种做法 1.互斥锁unlock。notify条件变量。2....
  • 为什么 if会出现虚假唤醒 因为if只会执行一次,执行完会接着向下执行if()外边的 而while不会,直到条件满足才会向下执行while()外边的 避免虚假唤醒 下面是避免虚假唤醒的示例: package com.jiang.pc; /** *...
  • 1、虚假唤醒产生原因 2、规避虚假唤醒 3、总结

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,657
精华内容 1,862
关键字:

wait虚假唤醒