notifyAll唤醒线程的范围?

今天看到开源中国上有这样一个问答:假设我有两个对象锁,对象A锁有5个线程在等待,对象B锁有3个线程在等待,对象A锁中的线程执行完,这时调用notifyAll,是唤醒了对象AB两个锁的全部的等待线程还是只唤醒了A锁的5个线程?

1. 方法文档解释

屏幕截图 2021-05-16 202936 通过看该方法文档的解释,可以得出下面结论:

  • notifyAll()中All的含义是所有的线程,而不是所有的锁,只能唤醒等待(调用wait()方法等待)同一个锁的所有线程。notifyAll()执行后,只有一个线程能得到锁,其他没有得到锁的线程会继续保持在等待状态。【notifyAll()只能释放一把锁。】
  • notifyAll()必须在当前线程拥有监视器锁的情况下执行,否则将抛出异常IllegalMonitorStateException。

2. 代码解释

定义两个对象锁,每个对象分别有两个进程,先将对象一里线程A与线程B启动,进入等待状态;在把对象二里的线程C启动,也进入等待状态;接着将对象二里的线程D启动并唤醒其他线程。

1package person.xsc.practice; 2 3public class ThreadWaitAndNotifyAll implements Runnable{ 4 private static Object object1 = new Object(); 5 private static Object object2 = new Object(); 6 @Override 7 public void run() { 8 synchronized (object1) { 9 System.out.println(Thread.currentThread().getName() + "获得锁,进入等待状态"); 10 try { 11 object1.wait(); 12 } catch (InterruptedException e) { 13 e.printStackTrace(); 14 } 15 System.out.println(Thread.currentThread().getName() + "执行最后部分结束"); 16 } 17 } 18 public static void main(String[] args) { 19 ThreadWaitAndNotifyAll runnable = new ThreadWaitAndNotifyAll(); 20 Thread threadA = new Thread(runnable,"线程A"); 21 Thread threadB = new Thread(runnable,"线程B"); 22 Thread threadC=new Thread(new Runnable() { 23 @Override 24 public void run() { 25 // TODO Auto-generated method stub 26 synchronized (object2) { 27 System.out.println(Thread.currentThread().getName() + "获得锁,进入等待状态"); 28 try { 29 object2.wait(); 30 } catch (InterruptedException e) { 31 e.printStackTrace(); 32 } 33 System.out.println(Thread.currentThread().getName() + "执行结束"); 34 } 35 } 36 37 },"线程D"); 38 Thread threadD = new Thread(new Runnable() { 39 @Override 40 public void run() { 41 synchronized (object2) { 42 System.out.println(Thread.currentThread().getName() + "获得锁,开始通知唤醒所有线程"); 43 // 唤醒其他线程 44 object2.notifyAll(); 45 // 调用完notifyAll()方法后,同步代码块中的其他代码,必须执行完后才能将对象锁释放,而不是调用了notifyAll()方法后立即释放。 46 System.out.println(Thread.currentThread().getName() + "执行结束"); 47 } 48 } 49 },"线程C"); 50 // 每次运行,线程0和线程1的顺序可能会不同,执行顺序由CPU决定 51 threadA.start(); 52 threadB.start(); 53 try { 54 Thread.sleep(100); 55 } catch (InterruptedException e) { 56 e.printStackTrace(); 57 } 58 threadC.start(); 59 threadD.start(); 60 } 61 } 62输出: 63线程A获得锁,进入等待状态 64线程B获得锁,进入等待状态 65线程D获得锁,进入等待状态 66线程C获得锁,开始通知唤醒所有线程 67线程C执行结束 68线程D执行结束 69

根据上面代码运行结果来看,确实如方法文档所说的那样:notifyAll()只能唤醒等待同一个锁的所有线程。

点赞
收藏

评论区

加载中...

相关推荐

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

3 Java对象的内存布局以及对象的访问定位

先来看看Java对象在内存中的布局一Java对象的内存布局在HotSpot虚拟机中,对象在内存中的布局分为3个区域对象头(Header)MarkWord(在32bit和64bit虚拟机上长度分别为32bit和64bit)存储对象自身的运行时数据,包括哈希码,GC分代年龄,锁状态标志,线程持有的锁,偏向线程ID,偏向时间戳等类型指

python中的各种锁

一、全局解释器锁(GIL)  1、什么是全局解释器锁      在同一个进程中只要有一个线程获取了全局解释器(cpu)的使用权限,那么其他的线程就必须等待该线程的全局解释器(cpu)使    用权消失后才能使用全局解释器(cpu),即时多个线程直接不会相互影响在同一个进程下也只有一个线程使用cpu,这样的机制称为全局    解释器锁(GIL)。 

Java并发包小结

1、Lock  Lock功能对应关键字synchrozied功能,lock和unlock方法用于加锁和释放锁。等待锁的线程加入到等待链表中,同时阻塞线程,锁释放时,从等待链表中取出等待的线程执行,取等待的线程分公平与非公平两种方式,公平方式取第一个等待的线程,非公平方式当前正在获取锁的线程可能立刻执行,而不用加入到等待队列中,排队执行。2、Con

Java并发 wait()、notify()和notifyAll()

一个线程修改一个对象的值,而另一个线程则感知到了变化,然后进行相应的操作,这就是wait()、notify()和notifyAll()方法的本质。具体体现到方法上则是这样的:一个线程A调用了对象obj的wait方法进入到等待状态,而另一个线程调用了对象obj的notify()或者notifyAll()方法,线程A收到通知后从对象obj的wait方法返回,继续

Python的锁

互斥锁锁通常被用来实现对共享资源的同步访问。为每一个共享资源创建一个Lock对象,lLock()创建一个锁,初始状态是未锁定当你需要访问该资源时,调用l.acquire方法来获取锁对象(如果其它线程已经获得了该锁,则当前线程需等待其被释放),待资源访问完后,再调用l.release方法释放锁!(https: