• 使用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>
  • 相关阅读:
    POJ 2594 Treasure Exploration(最大路径覆盖)
    POJ 2516 Minimum Cost(最小费用最大流)
    城市面积
    python strip()函数
    python sys.path.append
    python调用shell,python与shell间变量交互
    远程登陆强大命令screen
    pythonLevenshtein几个计算字串相似度的函数解析
    python 程序bug解决方案
    python 全局变量
  • 原文地址:https://www.cnblogs.com/jpfss/p/9620187.html
Copyright © 2020-2023  润新知