我有一个简单的代码片段
public class ItemManager {
private Integer itemCount = 0;
public void incrementAndPrint() {
synchronized(this) {
System.out.println(++itemCount + " ");
}
}
public static void main(String[] args) {
ItemManager manager = new ItemManager();
ExecutorService executor = Executors.newFixedThreadPool(20);
for (int i = 0; i < 10; i++) {
executor.submit(manager::incrementAndPrint);
}
executor.shutdown();
}
}
按预期产生 1 2 3 4 5 6 7 8 9 10 。我还可以使用对象实例创建另一个字段并锁定它
private Integer itemCount = 0;
private Object lock = new Object();
public void incrementAndPrint() {
synchronized(lock) {
System.out.println(++itemCount + " ");
}
}
它还会按预期产生 1 2 3 4 5 6 7 8 9 10 。
但是,如果我尝试锁定要递增和打印的同一个对象
private Integer itemCount = 0;
public void incrementAndPrint() {
synchronized(itemCount) {
System.out.println(++itemCount + " ");
}
}
该操作将保持原子性,但结果是无序的:2 1 3 4 5 6 7 8 9 10。
我知道synchronized(this)
或者同步整个方法将解决我所有的问题。我只是不明白为什么我可以锁定一个字段(Object lock
),但无法锁定另一个 (Integer itemCount
)?里面的所有东西不应该是synchronized
块是否可以正确锁定,无论该对象是什么,只要它是在所有线程之间共享的单个对象?
Integer
Java 中的 s 是不可变的。你打电话时++itemCount
,您实际上正在执行三个操作:首先,Integer
被拆箱到int
与价值Integer
。那么,这个原始的int
递增,最后递增的int
被自动装箱回Integer
。所以事实上,你最终拥有不同的 Integer
实例。由于您在不同的实例上进行同步,因此同步没有意义,并且您会看到无序打印。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)