为什么必须从同步方法或者块中调用wait(),notify()和notifyAll()方法
时间:2020-01-09 10:35:07 来源:igfitidea点击:
为什么必须从同步方法或者块中调用Java中的wait(),notify()和notifyAll()方法。这篇文章提供了一些要点,为什么在同步上下文中调用wait(),notify()和notifyAll()方法才有意义。
我们需要注意以下两点:
1 –正如我们必须知道的那样,Java中的每个对象都有一个与之关联的锁(也称为监视器)。当线程进入同步方法或者同步块时,它将获取该锁。尝试执行相同代码的所有其他线程(在同步方法或者同步块中)必须等待第一个线程完成并释放锁。
2 – wait(),notify()和notifyAll()方法的说明
- wait –使拥有对象的监视器锁的当前线程放弃锁并进入等待状态。
- notify –唤醒正在该对象的监视器上等待的单个线程。
- notifyAll –唤醒该对象的监视器上正在等待的所有线程。
使用这两点,我们只需要连接点即可理解为什么必须从同步方法或者块中调用Java中的wait(),notify()和notifyAll()方法。
从等待描述中可以清楚地看到,notify和notifyAll方法只能在线程拥有对象锁时在对象上调用这些方法。现在,线程何时拥有对象的锁?获取它并进入同步块或者方法后。因此,很明显,当线程具有对象的锁时,可以在同步上下文中调用wait(),notify()和notifyAll()方法。
从同步方法或者块外部调用方法
如果我们在未同步的方法中调用wait,notify和notifyAll方法,则该程序将编译,但是在运行该程序时,我们会收到IllegalMonitorStateException。
例如,在下面的代码中,从同步块中调用wait()方法,将编译代码,但在运行时将抛出IllegalMonitorStateException。
public void increment(){ synchronized(this){ for(int i = 1; i <= 5 ; i++){ System.out.println(Thread.currentThread().getName() + " i - " + i); } } try { // calling wait method outside synchronized context this.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
输出:
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Unknown Source) at com.theitroad.Counter.increment(SynchronizedDemo.java:10) at com.theitroad.SynchronizedDemo.run(SynchronizedDemo.java:31)