您的位置:首页 > 移动开发 > Objective-C

为什么Object.wait(),Object.notify(),Object.notifyAll()必须在同步块中执行呢?

2018-03-06 15:58 603 查看
背景介绍

代码示例

静态条件思路

PV操作思路

参考

背景介绍

在Java中,我们使用
wait()
nofify()
notifyAll()
来实现线程间通信。一个线程在测试条件不满足后进入等待状态。在经典的生产者-消费者问题中,生产者线程因缓存区满而等待,消费者线程在消费了缓存区的一个元素后通知生产者线程。

调用
notify()
notifyAll()
方法来通知一个或多个线程一个条件已经改变了。一旦通知线程退出同步方法或同步块,所有等待的线程会争抢它们等待对象上的对象锁。获取锁的线程会从等待状态返回并继续执行

代码示例

一般而言,使用Object的wait/notify进行现场通信代码如下图示,
wait()
notify()
都在同步块中执行.



wait()
notify()
不在同步块中执行,会出现什么情况呢?

/**
* @author pfjia
* @since 2018/3/6 15:40
*/
public class IllegalWaitDemo {
public static void main(String[] args) {
IllegalWaitDemo demo=new IllegalWaitDemo();
try {
demo.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


执行上述代码后,结果如下,抛出java.lang.IllegalMonitorStateException:

Exception in thread "main" java.lang.IllegalMonitorStateException
at java.base/java.lang.Object.wait(Native Method)
at java.base/java.lang.Object.wait(Object.java:516)
at pfjia.IllegalWaitDemo.main(IllegalWaitDemo.java:11)


但是为什么会抛出java.lang.IllegalMonitorStateException呢?

静态条件思路

试想在不加锁时,一个如下的操作顺序

生产者
while (!someCondition){ (1)
lock.wait(); (4)
}

消费者
satisfyCondition(); (2)
lock.notify(); (3)


由于
while(!someCondition){lock.wait()}
是一个先判断后执行的语句,因此一定存在
竞态条件
,当上述代码以标识的顺序执行时,由于在
!someCondition
为true后才执行
satisfyCondition()
满足该condition,因此将导致即使condition被满足了,
lock.wait()
还是会在
lock.notify()
之后执行,就相当于丢失了一次唤醒.如果只有一个消费者线程,则生产者将永远得不到唤醒.

PV操作思路

我是将

synchronized (lock){
while (!someCondition){ (1)
lock.wait(); (4)
}
}


看做P操作.



synchronized (lock){
satisfyCondition(); (2)
lock.notify(); (3)
}


看做V操作,而PV的资源含义则由
someCondition
satisfyCondition()
确定.

由于PV操作必须是原子操作,而若
wait()
notify()
不在同步块中,就无法保证
原子性
,所以
wait()
notify()
必须在同步块中执行.

参考

为什么wait和notify必须在同步方法或同步块中调用
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Java
相关文章推荐