锁对象应该是易变的(同步块,class 的多个实例)?
Should lock object be volatile (synchronized block, multiple instances of class)?
我从 class A 创建了三个对象。所有这三个对象都可以更新存储在 class A 的私有静态 volatile 变量中的值。更新这个变量是在一个具有特定条件的同步块。我想通过使用锁对象来同步块。
所以首先在 MainClass 中创建对象
A a1 = new A();
A a2 = new A();
A a3 = new A();
在此之后,对象开始过自己的生活。这是我的 class A.
的简化示例
public class A{
private static volatile String sharedVariable;
Object lockObject = new Object();
private void updateVariable(String newValue){
//... some code
synchronized(lockObject){
//... code to check whether to update the value
sharedVariable = newValue;
}
}
如果我想让synchronized块与classA的所有实例和所有线程同步,是否应该将lockObject声明为private static volatile?如果我使用 class (this) 来同步块,它会完成同样的事情吗?
我认为使用上面的代码 class A 的所有实例都会创建自己的 lockObject 并与之同步。因此,同步只会发生在每个实例(a1、a2 和 a3)中的线程中。这是正确的吗?
volatile 提供的是先发生后发生的保证,所有线程中的后续读取将看到最近写入的值。
此处不混合 volatile 和 static 的目的。
如果您将锁对象定义为实例变量,那么它会为A
的每个实例创建,这绝对是不希望的。
由于需要同步访问的对象是静态的,需要创建static final锁对象。 final
(虽然不是必需的,但这是一个很好的做法)确保锁对象可见并且在运行时不会更改,并且静态创建一个锁来访问对象
public class A{
private static volatile String sharedVariable;
private static final Object lockObject = new Object();
private void updateVariable(String newValue){
//... some code
synchronized(lockObject){
//... code to check whether to update the value
sharedVariable = newValue;
}
}
更多相关信息:
- Static versus non-static lock object in synchronized block
- What will happen if I put a static lock in a instance method?
对象级锁不足以保护 class 变量。您需要 class 级锁。
volatile
变量用于不同的目的。当您在一个线程中更新变量的值并从多个线程读取变量的值时,它很有用。
看看下面的解决方案。
- 按照 Gurwinder Singh 的建议使用静态最终锁
- 使用
synchronized(A.class)
更新静态变量
- 使用AtomicReference
相关 SE 问题:
When to use AtomicReference in Java?
Difference between volatile and synchronized in Java
我从 class A 创建了三个对象。所有这三个对象都可以更新存储在 class A 的私有静态 volatile 变量中的值。更新这个变量是在一个具有特定条件的同步块。我想通过使用锁对象来同步块。
所以首先在 MainClass 中创建对象
A a1 = new A();
A a2 = new A();
A a3 = new A();
在此之后,对象开始过自己的生活。这是我的 class A.
的简化示例public class A{
private static volatile String sharedVariable;
Object lockObject = new Object();
private void updateVariable(String newValue){
//... some code
synchronized(lockObject){
//... code to check whether to update the value
sharedVariable = newValue;
}
}
如果我想让synchronized块与classA的所有实例和所有线程同步,是否应该将lockObject声明为private static volatile?如果我使用 class (this) 来同步块,它会完成同样的事情吗?
我认为使用上面的代码 class A 的所有实例都会创建自己的 lockObject 并与之同步。因此,同步只会发生在每个实例(a1、a2 和 a3)中的线程中。这是正确的吗?
volatile 提供的是先发生后发生的保证,所有线程中的后续读取将看到最近写入的值。
此处不混合 volatile 和 static 的目的。
如果您将锁对象定义为实例变量,那么它会为A
的每个实例创建,这绝对是不希望的。
由于需要同步访问的对象是静态的,需要创建static final锁对象。 final
(虽然不是必需的,但这是一个很好的做法)确保锁对象可见并且在运行时不会更改,并且静态创建一个锁来访问对象
public class A{
private static volatile String sharedVariable;
private static final Object lockObject = new Object();
private void updateVariable(String newValue){
//... some code
synchronized(lockObject){
//... code to check whether to update the value
sharedVariable = newValue;
}
}
更多相关信息:
- Static versus non-static lock object in synchronized block
- What will happen if I put a static lock in a instance method?
对象级锁不足以保护 class 变量。您需要 class 级锁。
volatile
变量用于不同的目的。当您在一个线程中更新变量的值并从多个线程读取变量的值时,它很有用。
看看下面的解决方案。
- 按照 Gurwinder Singh 的建议使用静态最终锁
- 使用
synchronized(A.class)
更新静态变量 - 使用AtomicReference
相关 SE 问题:
When to use AtomicReference in Java?
Difference between volatile and synchronized in Java