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,但是由于我遵循了同步机制,所以没有给出结果,但是如果我们在类级实例变量中创建一个锁对象,它的效果很好。正确的代码段位于下面
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);
}
}
我想知道,当我们在方法内部创建锁定对象时会发生什么?在方法内部和作为实例变量的锁对象创建之间有什么区别?
答案 0 :(得分:2)
局部变量存储在线程堆栈中,并分别为每个线程创建。如果局部变量不是原始变量,则实例本身存储在堆中,而对对象的引用存储在线程堆栈中。这就是为什么局部变量是线程安全的。
由于全局变量存储在堆上,并且被多个线程共享/可见,因此它们需要同步。
因此,在第一个示例中,您正在为每个线程创建新的锁,因此多个线程仍然可以访问它。
Here's关于Java内存模型的精彩文章