博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Boolean类型同步锁引起异常的分析
阅读量:6080 次
发布时间:2019-06-20

本文共 1916 字,大约阅读时间需要 6 分钟。

原文地址 http://topic.csdn.net/u/20080710/19/f61cb4db-ddff-4457-a26a-4ea578b0cc6c.html?87447500

提问:【

 
public class MyTest {
public static void main(String[] args) throws Exception {
new TestThread().start();
new TestThread().start();
Thread.sleep(1000);
System.out.println("Doing something...");
synchronized (lock) {
lock = false; // 语句1
lock.notifyAll(); // 语句2
}
}
static volatile Boolean lock = true;
}
class TestThread extends Thread {
@Override
public void run() {
synchronized (MyTest.lock) {
while (MyTest.lock) {
try {
MyTest.lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(getId());
}
}
}
输出结果为
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等方法,由于并没有同步这个对象,而是同步的改变以前的那个,就会报出如上的异常。 我们来看代码
 
synchronized (lock) {
lock = false; // 语句1
lock.notifyAll(); // 语句2
}

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

解决方法

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

 
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}
//发现其内部对于自动打包,拆包只使用了2个固定的对象。所以可以用
synchronized (lock) {
lock = false; // 语句1
Boolean.TRUE.notifyAll(); // 语句2
}
// 直接使用那个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>

转载地址:http://cjhgx.baihongyu.com/

你可能感兴趣的文章
PHP创建XML文件讲解
查看>>
CentOS 6.3下搭建Web服务器
查看>>
linux学习历程
查看>>
UIImagePickerController拍照与摄像(转)
查看>>
Android中三种onClick事件的实现与对比
查看>>
python for else
查看>>
Python爬虫示例
查看>>
服务器信息收集
查看>>
SSH Secure Shell Client中文乱码的解决方法
查看>>
[Nagios] Error: Template &#39;timman&#39; specified in contact definition could not be not found (c
查看>>
iOS开发UI篇—推荐两个好用的Xcode插件(提供下载链接)
查看>>
ios成长之每日一遍(day 8)
查看>>
iOS开发UI篇—UIScrollView控件实现图片轮播
查看>>
jQuery源码分析系列(33) : AJAX中的前置过滤器和请求分发器
查看>>
IP地址的分类——a,b,c 类是怎样划分的
查看>>
编译Boost 详细步骤
查看>>
spring-mybatis-data-common程序级分表操作实例
查看>>
秒杀多线程第四篇 一个经典的多线程同步问题
查看>>
[连载]JavaScript讲义(03)--- JavaScript面向对象编程
查看>>
Redis 性能问题的记录
查看>>