1.问题说明:
这是对线程的一个简单的测试,对于同步资源i,给它上互斥锁synchronized,创建两个线程在i<20时随机的输出i,以下程序不会按照预想的在i不同时乱序输出1-20,它会让互斥锁失效。使得有的数可能重复输出,有的数可能没输出。
代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28public class SampleTestOfThread implements Runnable{
public static Integer i=new Integer(0);//声明一个Integer对象
@Override
public void run() {
// TODO Auto-generated method stub
while(true) {
synchronized(i) {
if(i<20) {
i++;
System.out.println("i="+i);
}else {
break;//超出20跳出循环
}
}
}
}
//入口方法
public static void main(String[] args) {
System.out.println(" 4dada"+i);
Thread t1=new Thread(new SampleTestOfThread());
Thread t2=new Thread(new SampleTestOfThread());
t1.start();
t2.start();
}
}
运行结果的一个例子:
2.原因:
在这个程序中,i一直都在变化,对这个程序来说i不是同一个对象,所以synchronized(对多个线程共享同一个对象起作用)失效。
3.底层原因分析:
1.通过jdk自带的javap命令工具对该类进行分析,到磁盘的相应位置输入 javap -v SampleTestOfThread.class
会得到如图:
从图中红框可以得到i++的原理:i=Integer.valueOf(i.intValue()+1);
此时我们看下Integer的源码:1
2
3
4
5
6public static Integer valueOf(int i){
if(i>=IntegerCache.low&&i<=IntergerCache.high)
return IntegerCache.cache[i+(-IntegerCache.low)];
return new Integer(i);
}
可以知道每次Integer.valueOf返回的都是一个新的i对象。
自然而然synchronized锁失去效果。