synchronized块是否总能正常工作?我现在很困惑!使用synchronized关键字时我错了吗?
代码段如下:
package com.company;
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new MyThread().start();
}
}
}
class MyThread extends Thread {
// no atomic
private static Integer count = 0;
@Override
public void run() {
while (true) {
synchronized (count) {
//synchronized (this) {
if (count > 100)
break;
count++;
System.out.println("ThreadId:" + currentThread().getId() + ","
+ "inc MyThread.count to : " + count);
}
}
}
}
结果是:
ThreadId:10,inc MyThread.count to : 2
ThreadId:9,inc MyThread.count to : 2
ThreadId:9,inc MyThread.count to : 4
ThreadId:9,inc MyThread.count to : 5
ThreadId:9,inc MyThread.count to : 6
....
我不知道为什么第10和第9行输出相同的值。
答案 0 :(得分:9)
你做错了。首先,您在更新的字段上进行同步。在同步块输入时,同步将保留在count
变量中的对象上,但您稍后会对其进行修改。因此,如果第二个线程在第一个线程已经增加一个值时启动,则第一个线程将在Integer.valueOf(0)
上同步,第二个线程将在Integer.valueOf(1)
上同步,并且它们不会等待彼此。
第二个问题是你在Integer
上进行同步,缓存的值很小,可能会在程序的完全不同的部分重用,所以你可能最终会等待一些完全不相关的东西。
请注意this
上的同步无效,因为this
是每个帖子中不同的MyThread
对象。
您可以在某些共享对象上修复代码同步,这些共享对象不会因执行而发生更改。为此目的创建一个特殊的锁对象更好:
class MyThread extends Thread {
private static final Object lock = new Object();
// no atomic
private static Integer count = 0;
@Override
public void run() {
while (true) {
synchronized (lock) {
...
}
}
}
}