在使用简单赋值初始化变量的情况下是否需要同步并且我不关心可能发生多次初始化的可能性?
就像这样:
public class Something {
private static volatile Collection<String> data;
protected static Collection<String> data() {
if (data == null) {
final Set<String> dataToSet = new HashSet<String>();
dataToSet.add("value 1");
dataToSet.add("value 2");
data = dataToSet;
}
return data;
}
}
答案 0 :(得分:2)
作业操作是原子。接下来,您拥有 volatile 修饰符,可确保在读/写之间发生之前的关系。因此,此处不需要同步。
当需要防止其他线程损坏数据时(通过锁定对象的监视器并确保只有一个线程可以同时进入关键代码块),请使用 Synchronization )
答案 1 :(得分:1)
虽然Hashset是同步集合,但是当你对data()方法的返回值进行操作时,你可能会在两个不同的HashSet上运行。
一个线程可以对此进行评估(if(data == null))为true并等待处理器时间,同时其他一些线程可以评估if(data == null)是否为true并且它将继续并初始化HashSet 。一段时间后,当第一个线程获得处理器时间时,它将从停止的位置恢复,第一个线程将再次初始化HashSet(将数据变量指向另一个对象)。同时,第二个线程可能正在处理不同的Hashset对象,该对象与第一个Thread操作的位置不同。
答案 2 :(得分:-1)
您不需要与静态变量初始化同步。
但是在多线程环境中访问静态变量时需要进行同步。
关于静态变量你应该知道两点:
与局部变量不同,静态变量和方法在Java中是不是线程安全的。它们实际上是Java应用程序中各种线程安全问题的常见原因。由于类的每个对象都具有相同的静态变量副本,因此需要通过类锁来保护它。这就是为什么如果你使用静态变量然后确保正确同步其访问以避免线程安全问题,包括竞争条件(使用静态变量不是线程安全的)。
当类加载到内存中时,会初始化静态字段或变量。它们按照在Java源文件中声明的顺序从上到下进行初始化。因此静态字段以线程安全方式初始化。
我认为这个解释对你的问题很清楚。希望它会有所帮助〜:D