zoukankan      html  css  js  c++  java
  • notify 和 notifyAll 的区别

    (一)先看一个 notify发生死锁的例子:

    http://blog.csdn.net/tayanxunhua/article/details/20998449

    (本文虽是转载,不过也加入了一些个人观点)
    JVM多个线程间的通信是通过 线程的锁、条件语句、以及wait()、notify()/notifyAll组成。
    下面来实现一个启用多个线程来循环的输出两个不同的语句:
    package com.tyxh.block;
     
    class OutTurn {
        private boolean isSub = true;
        private int count = 0;
     
        public synchronized void sub() {
              try {
                  while (!isSub ) {
                      this.wait();
                 }
                 System. out.println("sub ---- " + count);
                  isSub = false ;
                  this.notify();
             } catch (Exception e) {
                 e.printStackTrace();
             }
              count++;
     
        }
     
        public synchronized void main() {
              try {
                  while (isSub ) {
                      this.wait();
                 }
                 System. out.println("main (((((((((((( " + count);
                  isSub = true ;
                  this.notify();
             } catch (Exception e) {
                 e.printStackTrace();
             }
              count++;
        }
    }
    package com.tyxh.block;
     
    public class LockDemo {
        public static void main(String[] args) {
              // System.out.println("lock");
     
              final OutTurn ot = new OutTurn();
     
              for (int j = 0; j < 100; j++) {
     
                  new Thread(new Runnable() {
     
                      public void run() {
                           // try {
                           // Thread.sleep(10);
                           // } catch (InterruptedException e) {
                           // e.printStackTrace();
                           // }
                           for (int i = 0; i < 5; i++) {
                              ot.sub();
                          }
                     }
                 }).start();
     
                  new Thread(new Runnable() {
     
                      public void run() {
                           // try {
                           // Thread.sleep(10);
                           // } catch (InterruptedException e) {
                           // e.printStackTrace();
                           // }
                           for (int i = 0; i < 5; i++) {
                              ot.main();
                          }
                     }
                 }).start();
             }
     
        }
    }
     
    解释一下原因:
         OutTurn类中的sub和main方法都是同步方法,所以多个调用sub和main方法的线程都会处于阻塞状态,等待一个正在运行的线程来唤醒它们。下面分别分析一下使用notify和notifyAll方法唤醒线程的不同之处:
         上面的代码使用了notify方法进行唤醒,而notify方法只能唤醒一个线程,其它等待的线程仍然处于wait状态,假设调用sub方法的线程执行完后(即System. out .println("sub ---- " count )执行完之后),所有的线程都处于等待状态,此时在sub方法中的线程执行了isSub=false语句后又执行了notify方法,这时如果唤醒的是一个sub方法的调度线程,那么while循环等于true,则此唤醒的线程也会处于等待状态,此时所有的线程都处于等待状态,那么也就没有了运行的线程来唤醒它们,这就发生了死锁。
         如果使用notifyAll方法来唤醒所有正在等待该锁的线程,那么所有的线程都会处于运行前的准备状态(就是sub方法执行完后,唤醒了所有等待该锁的状态,注:不是wait状态),那么此时,即使再次唤醒一个sub方法调度线程,while循环等于true,唤醒的线程再次处于等待状态,那么还会有其它的线程可以获得锁,进入运行状态。
     
         总结:notify方法很容易引起死锁,除非你根据自己的程序设计,确定不会发生死锁,notifyAll方法则是线程的安全唤醒方法。
     
     
     
    notify和notifyAll的区别:

    notify()和notifyAll()都是Object对象用于通知处在等待该对象的线程的方法。

    void notify(): 唤醒一个正在等待该对象的线程。
    void notifyAll(): 唤醒所有正在等待该对象的线程。
    两者的最大区别在于:
         notifyAll使所有原来在该对象上等待被notify的线程统统退出wait的状态,变成等待该对象上的锁,一旦该对象被解锁,他们就会去竞争。
         notify他只是选择一个wait状态线程进行通知,并使它获得该对象上的锁,但不惊动其他同样在等待被该对象notify的线程们,当第一个线程运行完毕以后释放对象上的锁,此时如果该对象没有再次使用notify语句,即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,继续处在wait状态,直到这个对象发出一个notify或notifyAll,它们等待的是被notify或notifyAll,而不是锁。 

     

     

     
     
     
    (二)再看一个例子:
    https://www.zhihu.com/question/37601861
     
    作者:Alex Wang
    链接:https://www.zhihu.com/question/37601861/answer/94679949
    来源:知乎
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    还是直接上代码:
    public class WaitAndNotify {
    public static void main(String[] args) {
            Object co = new Object();
            System.out.println(co);
    
            for (int i = 0; i < 5; i++) {
                MyThread t = new MyThread("Thread" + i, co);
                t.start();
            }
    
    try {
                TimeUnit.SECONDS.sleep(2);
                System.out.println("-----Main Thread notify-----");
                synchronized (co) {
                    co.notify();
                }
    
                TimeUnit.SECONDS.sleep(2);
                System.out.println("Main Thread is end.");
    
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
    static class MyThread extends Thread {
    private String name;
            private Object co;
    
            public MyThread(String name, Object o) {
    this.name = name;
                this.co = o;
            }
    
    @Override
            public void run() {
                System.out.println(name + " is waiting.");
                try {
    synchronized (co) {
    co.wait();
                    }
                    System.out.println(name + " has been notified.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    
    运行结果
    java.lang.Object@1540e19d
    Thread1 is waiting.
    Thread2 is waiting.
    Thread0 is waiting.
    Thread3 is waiting.
    Thread4 is waiting.
    -----Main Thread notify-----
    Thread1 has been notified.
    Main Thread is end.
    
    将其中的那个notify换成notifyAll运行结果
    Thread0 is waiting.
    Thread1 is waiting.
    Thread2 is waiting.
    Thread3 is waiting.
    Thread4 is waiting.
    -----Main Thread notifyAll-----
    Thread4 has been notified.
    Thread2 has been notified.
    Thread1 has been notified.
    Thread3 has been notified.
    Thread0 has been notified.
    Main Thread is end.
    
    运行环境jdk8结论
    notify唤醒一个等待的线程notifyAll唤醒所有等待的线程

    notify 与 nofityall,notify造成死锁实践

  • 相关阅读:
    Unity网格合并_材质合并
    windows7任务管理器内存相关列详细解释
    移动平台unity3d优化
    各种移动GPU压缩纹理的使用方法
    opengl VAO ,VBO
    GPU 与CPU的作用协调,工作流程、GPU整合到CPU得好处
    Unity3d的批渲染 batch rendering
    Android真机调测Profiler
    图片占用内存计算方法
    Unity3D–Texture图片空间和内存占用分析
  • 原文地址:https://www.cnblogs.com/silyvin/p/9106676.html
Copyright © 2011-2022 走看看