• 使用Boolean类型同步锁引起异常的分析


    原文地址 http://topic.csdn.net/u/20080710/19/f61cb4db-ddff-4457-a26a-4ea578b0cc6c.html?87447500 http://www.java2000.net/viewthread.jsp?tid=7085

    提问:【tteesstt

    1. public class MyTest {
    2. public static void main(String[] args) throws Exception {
    3. new TestThread().start();
    4. new TestThread().start();
    5. Thread.sleep(1000);
    6. System.out.println("Doing something...");
    7. synchronized (lock) {
    8. lock = false; // 语句1
    9. lock.notifyAll(); // 语句2
    10. }
    11. }
    12. static volatile Boolean lock = true;
    13. }
    14. class TestThread extends Thread {
    15. @Override
    16. public void run() {
    17. synchronized (MyTest.lock) {
    18. while (MyTest.lock) {
    19. try {
    20. MyTest.lock.wait();
    21. } catch (InterruptedException e) {
    22. e.printStackTrace();
    23. }
    24. }
    25. System.out.println(getId());
    26. }
    27. }
    28. }
    输出结果为
    Doing something...
    Exception in thread "main" java.lang.IllegalMonitorStateException
    at java.lang.Object.notifyAll(Native Method)
    at MyTest.test(MyTest.java:13)
    at MyTest.main(MyTest.java:3
    如果把语句1和语句2调换一下就正常了。 大家给诊断一下,到底是为什么?
    讨论过程请大家自行参考原始的帖子和我的整理帖子,这里只给出最终的分析结果
    分析
    当作为同步锁的对象发生改变时,比如换了一个新的对象,那么如果在新的对象上调用同步的wait等方法,由于并没有同步这个对象,而是同步的改变以前的那个,就会报出如上的异常。 我们来看代码
    1. synchronized (lock) {
    2. lock = false; // 语句1
    3. lock.notifyAll(); // 语句2
    4. }

    语句1那里修改了lock的对象指向,结果造成下面的一句notifyAll使用了一个并没有synchronized的对象,随意报出了异常。

    解决方法

    方案1,使用Boolean的特殊性 由于 lock=false;的特殊性,分析Boolean的源代码发现

    1. public static final Boolean TRUE = new Boolean(true);
    2. public static final Boolean FALSE = new Boolean(false);
    3. public static Boolean valueOf(boolean b) {
    4. return (b ? TRUE : FALSE);
    5. }
    6. //发现其内部对于自动打包,拆包只使用了2个固定的对象。所以可以用
    7. synchronized (lock) {
    8. lock = false; // 语句1
    9. Boolean.TRUE.notifyAll(); // 语句2
    10. }
    11. // 直接使用那个TRUE就行了。

    方法2:使用一个参数可变对象,而不是不可变的

    比如

    class MyLock {

       boolean lock = true;

      }

     static volatile MyLock lock = new MyLock();

      // 然后再代码里面用  

    lock.lock=false;// 进行标志的变更和判断就可以了

    结论:

    同步锁最好单独使用,如果锁自身附带了其它作用,应使用一个可变的对象 推荐

    static volatile MyLock lock = new MyLock();
    应该写成
    final static volatile MyLock lock = new MyLock();






    <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
  • 相关阅读:
    gzip 压缩格式的网站处理方法---sina.com 分类: python python基础学习 2013-07-16 17:40 362人阅读 评论(0) 收藏
    自定义系统命令缩写 分类: ubuntu 2013-07-15 17:42 344人阅读 评论(0) 收藏
    线程 ing 分类: python 2013-07-15 14:28 197人阅读 评论(0) 收藏
    [模板]排序
    [BFS] [洛谷] P1032 字串变换
    [二分答案][洛谷] P1316 丢瓶盖
    [二分] [POJ] 2456 Aggressive cows
    [贪心] [STL] [51nod] 做任务三
    [BFS] [记忆化] [洛谷] P1141 01迷宫
    [DFS] [记忆化] [洛谷] P1434 [SHOI2002]滑雪
  • 原文地址:https://www.cnblogs.com/jpfss/p/9620187.html
Copyright © 2020-2023  润新知