java - java线程同步和锁定没有效果?
问题描述
非常困惑为什么我在同步或锁定方法中执行“i++”时会得到随机结果?
public class aaa implements Runnable {
static int count = 0;
public static void main(String[] args) {
aaa aaa = new aaa();
aaa.create();
}
public void create() {
ExecutorService executor = Executors.newFixedThreadPool(100);
for (int i = 0; i < 1000; i++) {
aaa thread = new aaa();
executor.execute(thread);
}
executor.shutdown();
while (true){
if(executor.isTerminated()){
System.out.println("a " + count);
break;
}
}
}
@Override
public void run() {
this.test();
}
public void test() {
Lock lock = new ReentrantLock();
try {
lock.lock();
count++;
System.out.println(count);
} finally {
lock.unlock();
}
}
}
或者:
public synchronized void test() {
count++;
System.out.println(count);
}
结果是一个随机数,有时是 1000,有时是 998、999 ...等等,并且“测试”方法内部的打印不是按顺序排列的,就像:
867
836
825
824
821
820
819
817
816
a 999
但是,如果它在同步块中,一切看起来都很好:
public void test() {
synchronized (aaa.class) {
count++;
System.out.println(count);
}
}
结果:
993
994
995
996
997
998
999
1000
a 1000
我认为上面所有的方法都应该给我相同的结果1000,并且自增应该是顺序的,但只有最后一种方法有效。代码有什么问题?请帮忙!!!
解决方案
您正在创建 aaa 的多个实例,每个实例都会创建自己的 ReentrantLock,并且每个执行中的线程都会顺利地从自己的实例中获取锁。
public void test() {
Lock lock = new ReentrantLock();
try {
lock.lock();
count++;
System.out.println(count);
} finally {
lock.unlock();
}
}
由于 aaa 有多个实例,每个线程都在自己的实例上运行,同步方法使用 aaa.class 的当前对象
public synchronized void test() {
count++;
System.out.println(count);
}
在这种方法中获得正确结果的原因是,您使用 aaa.class 作为同步对象
public void test() {
synchronized (aaa.class) {
count++;
System.out.println(count);
}
}
解决方案是,在所有线程中重用相同的锁(ReentrantLock)。将锁定义在与变量计数相同的级别将解决该问题。