用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字

路易斯陈凯瑞    -  云代码空间

—— 天行健,君子以自强不息。地势坤,君子以厚德载物

Object的wait 和notify的思考

2014-08-14|1507阅||

摘要:java源代码中关于wait和notify的说明有一点是必须在同步块中使用,为什么要这样做呢

关于wait和notify的定义以及使用在java api和《java线程》中都有很详细的说明,这里只是关于wait notify使用时一定要在同步块中这一点进行一些个人思考。

如果纯粹从使用出发解释这个问题,很简单,如果不在同步块中使用,java会抛出IllegalMonitorStateException,这是java API本身的限制。

再深入一点,java为什么要加这个限制?因为这两个方法就是设计给多线程用的,如果你的代码没有多线程或者多线程问题,当然不需要用到这两个方法。

然而这也只是API设计的结果,那么设计的初衷又是什么呢?
首先看一下wait的一段解释:
Note that the <tt>wait</tt> method, as it places the current thread
     * into the wait set for this object, unlocks only this object; any
     * other objects on which the current thread may be synchronized remain
     * locked while the thread waits.
通过这段解释我们可以看到wait的行为是将当前线程放到持有对象的wait set,释放持有对象的锁,目的应该是让其他线程有机会持有该对象的锁。
这里包含两个行为
1)当前线程加入到对象的wait set
    这一点其实就是观察者的实现,避免了循环轮询的CPU消耗,改成了监听通知的模式,可以理解,好像和同步不同步没啥关系
2) 释放对象锁
    如果wait不在同步块中,就没有办法保证当前线程持有了对象的锁,这个时候如果贸然释放对象锁,很有可能造成错误(释放了别人的锁?当然这已经通过限制避免了),所以个人认为这一点才是wait方法需要在同步块中的原因。

再看notify方法,解释比较长就不贴了,行为很简单
唤醒当前对象的wait set中的任意(arbitrary)一个线程,让该线程有机会去竞争这个对象的锁。
    试想,如果notify不在同步块中,那么就没有办法保证当前线程获取了对象的锁,同样对象的锁什么时候会释放也就是个不确定因素;这个时候唤醒一个等待状态的线程加入竞争并没有太大意义,因为你既没有一个可用的资源给他竞争也不确定未来是否会有资源。如果notify在同步块中,那么至少在当前同步块退出的时候就会释放对象锁,使当前对象变成竞争资源。

当然以上观点都是在看《java 线程》时候的一些思考,从方法行为上去揣测设计者的初衷以便更好的理解API,欢迎探讨拍砖

顶 1踩 0收藏
文章评论
    发表评论

    个人资料

    • 昵称: 路易斯陈凯瑞
    • 等级: 中级程序员
    • 积分: 236
    • 代码: 4 个
    • 文章: 3 篇
    • 随想: 0 条
    • 访问: 5 次
    • 关注

    最新提问

      站长推荐