使用Boolean类型同步锁引起异常的分析
原文地址 http://topic.csdn.net/u/20080710/19/f61cb4db-ddff-4457-a26a-4ea578b0cc6c.html?87447500 http://www.java2000.net/viewthread.jsp?tid=7085
提问:【tteesstt】
-
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());
-
}
-
}
-
}
输出结果为
当作为同步锁的对象发生改变时,比如换了一个新的对象,那么如果在新的对象上调用同步的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>
使用Boolean类型同步锁引起异常的分析的更多相关文章
- Lock同步锁--线程同步
Lock-同步锁 Lock是java5提供的一个强大的线程同步机制--通过显示定义同步锁对象来实现同步.Lock可以显示的加锁.解锁.每次只能有一个线程对lock对象加锁. Lock有ReadLock ...
- 线程同步 synchronized 同步代码块 同步方法 同步锁
一 同步代码块 1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块.其语法如下: synchronized(obj){ // ...
- python并发编程之多进程(二):互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型
一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终 ...
- Java同步锁——lock与synchronized 的区别【转】
在网上看来很多关于同步锁的博文,记录下来方便以后阅读 一.Lock和synchronized有以下几点不同: 1)Lock是一个接口,而synchronized是Java中的关键字,synchroni ...
- 并发,同步锁,Runnable,Callable,Future
1.并发: 在我们的操作系统中,同一个时间点,有N个线程都想访问同一个程序!但是cpu只能运行一个! 这种情况就是! 多个线程在 同一个时间点 访问同一个资源,会引发线程不安全的问题! 怎么解决这种不 ...
- 结合 Redis 实现同步锁
1.技术方案 1.1.redis的基本命令 1)SETNX命令(SET if Not eXists) 语法:SETNX key value 功能:当且仅当 key 不存在,将 key 的值设为 val ...
- Java同步锁全息详解
一 同步代码块 1.为了解决并发操作可能造成的异常,java的多线程支持引入了同步监视器来解决这个问题,使用同步监视器的通用方法就是同步代码块.其语法如下: synchronized(obj){ // ...
- python开发进程:互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型
一,互斥锁,同步锁 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 竞争带来的结果就是错乱,如何控制,就是加锁处理 part1:多个进程共享同一打印终 ...
- Java多线程系列 基础篇06 synchronized(同步锁)
转载 http://www.cnblogs.com/paddix/ 作者:liuxiaopeng http://www.infoq.com/cn/articles/java-se-16-synchro ...
随机推荐
- 推荐一个iOS应用UI界面设计站点
Patterns是一个分享ios应用UI界面的站点,专注于分享iOS应用UI界面的细节.依照设计元素进行分类,依照iOS经常使用功能对各类UI进行分类展示. 链接:url=http%3A%2F%2Fw ...
- jQuery的原理
JQ的原理 jquery-1.xxx :专门为PC端诞生的类库,兼容所有的浏览器 jquery-2.xxx:当初是为了移动端而准备的,所以IE低版本浏览器一般不兼容,但是这个版本针对移动端的事件等操作 ...
- angular 响应式自定义表单控件—注册头像实例
1. 组件继承ControlValueAccessor,ControlValueAccessor接口需要实现三个必选方法 writeValue() 用于向元素中写入值,获取表单的元素的元素值 regi ...
- 【Educational Codeforces Round 31 B】Japanese Crosswords Strike Back
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 所有数字的和加上n-1,如果为x则唯一,否则不唯一 [代码] #include <bits/stdc++.h> usin ...
- 【】maze
[链接]点击打开链接 [题意] 小 T 被放到了一个迷宫之中,这个迷宫由 n 个节点构成,两个节点之间可能存在多条无 向边,小 T 的起点为 1 号节点,终点为 n 号节点.有 m 条无向边,对于每一 ...
- 每日技术总结:flex,选项卡,classList,
1.Flex布局子元素垂直居中 给父元素添加以下样式: .parent { display: flex; align-items: center; } 2.js面向对象的选项卡 见另一篇文章 js面向 ...
- POJ 3159 Candies 还是差分约束(栈的SPFA)
http://poj.org/problem?id=3159 题目大意: n个小朋友分糖果,你要满足他们的要求(a b x 意思为b不能超过a x个糖果)并且编号1和n的糖果差距要最大. 思路: 嗯, ...
- 字符的输入和输出即:getchar和putchar
#include <stdio.h> int main(int argc, const char * argv[]) { putchar(getchar());//这种方式就是输入一个字符 ...
- php 发送QQ邮箱邮件
这是我的源码比较简陋 https://www.lanzous.com/i2l7h8f 感谢 https://www.cnblogs.com/woider/p/6980456.html 下载phpmai ...
- 7、linux系统2440开发板域名解析问题
如果在linux系统中ping某一台电脑的ip地址可以ping 通: ~ >: ping 192.168.1.3PING 192.168.1.3 (192.168.1.3): 56 data b ...