在此oracle example内部锁等等,监视器对象从未被声明为 volatile、final 或与任何其他常规对象没有任何区别
public class MsLunch { private long c1 = 0; private long c2 = 0; private Object lock1 = new Object(); private Object lock2 = new Object(); public void inc1() { synchronized(lock1) { c1++; } } public void inc2() { synchronized(lock2) { c2++; } } }
有很多问题争论 volatile block 与同步块(synchronized block)
- volatile fields and synchronized blocks ,
- difference between volatile and synchronized in java
- when to use volatile vs synchronization in multithreading in java ,
- do you ever use the volatile keyword in java
和不可变对象(immutable对象)
- what are immutable objects ,
- immutability and synchronization in java
- immutable objects java concurreny )在多线程中。
作为旁注,我理解声明对象为最终对象与不变性之间的细微差别 why-can-final-object-be-modified以及为什么将锁对象声明为final不会使其不可变。
但是,我们有著名的模式 singleton class惰性初始化,其中使用 volatile
变量是必不可少的。
public class SingletonDemo { private static volatile SingletonDemo instance; private SingletonDemo() { } public static SingletonDemo getInstance() { if (instance == null ) { synchronized (SingletonDemo.class) { if (instance == null) { instance = new SingletonDemo(); } } } return instance; } }
上面的code example使用 Class 对象作为锁。
既然对于多线程访问的对象需要使用上面的某种机制来保证原子访问,为什么对于内嵌锁对象不需要任何特殊处理呢?
最佳答案
这些锁不需要特殊处理,因为 MsLunch
对象本身需要先发布,然后才能被任何其他线程看到。
public class MyMain {
public static void main(String... args) {
MsLunch lunch = new MsLunch();
// ...
这是线程安全的,因为局部变量(“lunch
”)对于多个线程不可见。
接下来,下面的类使本地引用对系统中的所有线程可见。当这种情况发生时,我们需要使用 volatile
。 volatile
关键字有效地创建了安全发布对象的内存屏障。这包括分配之前进行的所有写入,包括构造对象时内部进行的写入。
C.f. Safe Publication
public class MyMain {
public static volatile MsLunch publicLunch;
public static void main(String... args) {
MsLunch lunch = new MsLunch();
publicLunch = lunch;
//...
}
}
关于java - 为什么内在锁对象不需要特殊处理(static、final、volatile)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35686765/