原文地址 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>

使用Boolean类型同步锁引起异常的分析的更多相关文章

  1. Lock同步锁--线程同步

    Lock-同步锁 Lock是java5提供的一个强大的线程同步机制--通过显示定义同步锁对象来实现同步.Lock可以显示的加锁.解锁.每次只能有一个线程对lock对象加锁. Lock有ReadLock ...

  2. 线程同步 synchronized 同步代码块 同步方法 同步锁

    一 同步代码块 1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块.其语法如下: synchronized(obj){ // ...

  3. python并发编程之多进程(二):互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型

    一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终 ...

  4. Java同步锁——lock与synchronized 的区别【转】

    在网上看来很多关于同步锁的博文,记录下来方便以后阅读 一.Lock和synchronized有以下几点不同: 1)Lock是一个接口,而synchronized是Java中的关键字,synchroni ...

  5. 并发,同步锁,Runnable,Callable,Future

    1.并发: 在我们的操作系统中,同一个时间点,有N个线程都想访问同一个程序!但是cpu只能运行一个! 这种情况就是! 多个线程在 同一个时间点 访问同一个资源,会引发线程不安全的问题! 怎么解决这种不 ...

  6. 结合 Redis 实现同步锁

    1.技术方案 1.1.redis的基本命令 1)SETNX命令(SET if Not eXists) 语法:SETNX key value 功能:当且仅当 key 不存在,将 key 的值设为 val ...

  7. Java同步锁全息详解

    一 同步代码块 1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块.其语法如下: synchronized(obj){ // ...

  8. python开发进程:互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型

    一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终 ...

  9. Java多线程系列 基础篇06 synchronized(同步锁)

    转载 http://www.cnblogs.com/paddix/ 作者:liuxiaopeng http://www.infoq.com/cn/articles/java-se-16-synchro ...

随机推荐

  1. setInterval()第一个参数带引号和不带引号的区别

    setInterval()第一个参数带引号和不带引号的区别:关于定时函数setInterval()的基本用法这里就不做介绍了,查阅相关教程即可,这里主要介绍一下setInterval()函数的第一个参 ...

  2. StringBuilder类的使用总结

    String 对象是不可改变的.每次使用 System.String 类中的方法之一时,都要在内存中创建一个新的字符串对象,这就需要为该新对象分配新的空间.在需要对字符串执行重复修改的情况下,与创建新 ...

  3. selenium 自动化基础知识(各种定位)

    元素的定位 webdriver 提供了一很多对象定位方法  例如: [ id ] , name , class name , link text , partial link text , tag n ...

  4. C# 文件转byte数组,byte数组再转换文件

    using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using Sy ...

  5. [Angular] Style HTML elements in Angular using ngStyle

    We will learn how to make use of the ngStyle directive to directly add multiple style attributes to ...

  6. js进阶 13 jquery动画函数有哪些

    js进阶 13 jquery动画函数有哪些 一.总结 一句话总结: 二.jquery动画函数有哪些 原生JavaScript编写动画效果代码比较复杂,而且还需要考虑兼容性.通过jQuery,我们使用简 ...

  7. Java核心技术 卷Ⅰ 基础知识(3)

    第五章 继承 继承已存在的类就是复用这些类的方法和域.反射是指在程序运行期间发现更多的类及其属性的能力. . 反射 . 使用反射编写泛型数组代码 继承设计的技巧

  8. windows下安装cmake

    windows下安装cmake 下载地址 download -> cmake-3.12.0-rc2-win64-x64.msi 安装 验证cmake --version

  9. POJ 2536 Gopher II (ZOJ 2536) 二分图匹配

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1882 http://poj.org/problem?id=2536 题目大 ...

  10. POS的一点杂笔

    仅限于POS 仅限于POS 仅限于POS A 字母字符 N 数字 S 特殊字符 an 字母和数字字符 as 字母和特殊字符 ns 数字和特殊字符 ans 字母.数字和特殊字符 MM 月份 DD 日期 ...