package com.i3geek.pattern.singleton.test;
public class MyTest {
public static void main(String[] args) {
new MyThread("kang-01").start();
new MyThread("kang-02").start();
new MyThread("kang-03").start();
}
}
class MyThread extends Thread{
private static Integer i = 1;
private static Object obj = new Object();
public MyThread() {
}
public MyThread(String threadName) {
super.setName(threadName);
}
@Override
public void run() {
show();
}
public void show(){
for(boolean flag = true; flag;){
synchronized (obj) { //问题:这里的使用obj作为锁是线程安全的?使用i作为线程是不安全的?
if(i<=50){
System.out.println(Thread.currentThread().getName()+" - " + i++);
try {
Thread.currentThread().sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
flag = false;
}
}
}
}
}
经过测试发现使用 i 变量作为锁不是线程安全的,而使用obj确是线程安全的
我觉得这个问题有点搞笑, Integer 继承自 Object(Object都可以,Integer怎么会不行?), 并且Integer i = 1, 会使用IntegerCache, 将i 指向同一个 1 的包装类型常量, 怎么会不行呢?
问题在于: 你在循环内部,改变了 i 的值,不断的改变锁,当然就出问题了,锁是不能改变的!