【发布时间】:2018-10-09 05:07:05
【问题描述】:
public class SampleExecutorService {
private static int count = 0;
private void increment() {
Object lock = new Object();
synchronized (lock) {
count++;
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
SampleExecutorService obj = new SampleExecutorService();
Runnable task = obj::increment;
for (int i = 0; i < 1000; i++) {
executorService.submit(task);
}
executorService.shutdown();
try {
executorService.awaitTermination(2, TimeUnit.MINUTES);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("count : " + count);
}
}
上述程序的预期结果是1000,但由于我遵循同步机制,它没有给出这个结果。但是如果我们在类级实例变量中创建一个锁对象,它就可以正常工作。正确的代码sn-p在下面
public class SampleExecutorService {
private static int count = 0;
Object lock = new Object();
private void increment() {
//Object lock = new Object();
synchronized (lock) {
count++;
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
SampleExecutorService obj = new SampleExecutorService();
Runnable task = obj::increment;
for (int i = 0; i < 1000; i++) {
executorService.submit(task);
}
executorService.shutdown();
try {
executorService.awaitTermination(2, TimeUnit.MINUTES);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("count : " + count);
}
}
我想知道,当我们在方法中创建锁对象时会发生什么?在方法内创建锁定对象和作为实例变量有什么区别?
【问题讨论】:
-
您正在为每个调用创建一个新的、单独的锁定对象,因此实际上根本没有锁定,因为每个调用都锁定一个 不同的 对象。实际上,您将有 10 个线程在没有任何同步的情况下同时修改您的计数器,从而为竞争条件和可见性问题留出空间。
-
每个方法调用都会创建自己的调用堆栈,因此在第一个示例中锁是没有意义的。
-
由于您只创建了 1 个
SampleExecutorService实例,因此差异是 1000 个锁定对象(在方法内部创建)vs 1 个锁定对象(对于SampleExecutorService实例)。 -
谢谢!我能够理解你的答案。它消除了我对这个问题的所有疑虑
标签: java multithreading concurrency synchronization executorservice