为什么计数本身的同步不起作用



为什么对计数进行同步不能使其安全?

class Increment implements Runnable{
static Integer count = new Integer(0);
public void run(){
for (int i = 0; i< 1_000_000; i++){
synchronized (count){
count ++;
}
}
}
public static void main(String[] args) throws InterruptedException {
Thread one = new Thread(new Increment());
Thread two = new Thread(new Increment());
one.start();
two.start();
one.join();
two.join();
System.out.print(count);
}
}
1555622

我知道我是否会在那里放一些像这样的虚拟物体

class Increment implements Runnable{
static Integer count = new Integer(0);
static Object o = new Object();
public void run(){
for (int i = 0; i< 1_000_000; i++){
synchronized (o){
count ++;
}
}    }
public static void main(String[] args) throws InterruptedException {
Thread one = new Thread(new Increment());
Thread two = new Thread(new Increment());
one.start();
two.start();
one.join();
two.join();
System.out.print(count);
}
}
2000000

那是安全的。但我不明白为什么它在计数本身上不起作用

因为锁不在变量上,而是在对象上。Integer是不可变的,当你递增它时,你会得到一个新的对象,这会替换你锁定的对象。每次线程试图进入同步块时,它都会评估带括号的表达式,以找到它应该锁定的内容。

这就造成了这样一种情况,即一个线程锁定了旧对象,而传入线程锁定了新对象,并且同步块中可以有两个线程。

您的固定解决方案之所以有效,是因为线程都共享同一个锁,而且它不会更改。

最新更新