当我们在方法中创建锁(同步块)对象时会发生什么?
What will happen when we create lock (Synchronized block) object inside a method?
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,但它没有给出该结果,因为我遵循了同步 mechanism.But 如果我们在 class 级实例变量中创建一个锁对象,它工作正常。正确的代码片段如下
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);
}
}
我想知道,当我们在方法中创建锁对象时会发生什么?在方法内部创建锁对象和作为实例变量创建锁对象有什么区别?
局部变量存储在线程堆栈中,并为每个线程单独创建。如果局部变量不是原始变量,则实例本身存储在堆上,但对对象的引用存储在线程堆栈上。这就是为什么局部变量是线程安全的。
由于全局变量存储在堆上并且被多个线程 shared/visible 需要同步。
因此在您的第一个示例中,您为每个线程创建了新锁,因此多个线程仍然可以访问它。
Here's 一篇关于 Java 内存模型的优秀文章
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,但它没有给出该结果,因为我遵循了同步 mechanism.But 如果我们在 class 级实例变量中创建一个锁对象,它工作正常。正确的代码片段如下
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);
}
}
我想知道,当我们在方法中创建锁对象时会发生什么?在方法内部创建锁对象和作为实例变量创建锁对象有什么区别?
局部变量存储在线程堆栈中,并为每个线程单独创建。如果局部变量不是原始变量,则实例本身存储在堆上,但对对象的引用存储在线程堆栈上。这就是为什么局部变量是线程安全的。
由于全局变量存储在堆上并且被多个线程 shared/visible 需要同步。
因此在您的第一个示例中,您为每个线程创建了新锁,因此多个线程仍然可以访问它。
Here's 一篇关于 Java 内存模型的优秀文章