gpt4 book ai didi

java - 在线程安全单例中,返回是否必须在同步块(synchronized block)内

转载 作者:行者123 更新时间:2023-12-03 12:43:56 26 4
gpt4 key购买 nike

考虑以下代码:

private static Singleton singleton;

public static Singleton get(){
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
return singleton; // <-- this part is important
}
这是来自 this question 的后续讨论。 .最初,我认为它是线程安全的。然而,一些受人尊敬的用户认为这不是线程安全的,因为 return singletonsynchronized堵塞。然而,其他一些(受人尊敬的)用户则持不同观点。
看完 do we need volatile when implementing singleton using double-check locking , 我改变主意了。 (该问题的代码):
    private static Singleton instance;

private static Object lock = new Object();

public static Singleton getInstance() {
if(instance == null) {
synchronized (lock) {
if(instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
(众所周知,为什么在第二个代码中需要 volatile。)
但是,在再次查看这两个示例后,我注意到第一个和第二个代码片段之间存在很大差异。前者最外层 ifsynchronized 内子句因此在 synchronized 中运行的所有线程 block 将强制发生之前的关系(即,如果正确设置了实例,线程将无法返回 null)或者我错了吗?我希望采取以下行动顺序:
lock monitor
...
unlock monitor
...
read singleton
我注意到所有与第一个代码片段相似的在线示例在 synchronized 中都有返回。堵塞;然而,这可能仅仅是因为在性能方面它是相同的,因为线程必须同步,所以为什么不安全起见,把 return 放在里面呢?!
问题:
是否返回 真的需要在 synchronized里面堵塞?读取返回语句的单例值是否可以看到 synchronized 之前的单例值?阻止开始?

最佳答案

Does the return really needs to be inside the synchronized block?


没有 return不需要在 synchronized 中阻止,除非 singleton字段可以分配到别处。但是, return 没有充分的理由。不应该在同步块(synchronized block)内。如果整个方法包含在同步中,那么如果我们在 Singleton 中,您只需将该方法标记为同步即可。在这里上课。如果单例在其他地方被修改,这会更干净更好。
至于为什么不需要在里面,因为您使用的是 synchronized block ,在 block 的开头有一个读屏障,在最后有一个写屏障,这意味着线程将获得最新值 singleton它只会被分配一次。
读内存屏障确保线程将看到更新的单例,这将是 null或完全发布的对象。写内存屏障确保对 singleton 的任何更新将被写入主存,其中包括 Singleton 的完整结构并将其发布到 singleton field 。程序顺序保证 singletonsynchronized 内分配除非另一个线程中有另一个赋值给 singleton,否则 block 将作为相同的值返回那么它将是未定义的。
如果您执行以下操作,程序顺序将更加有效。我倾向于在 singleton 时这样做是 volatile (使用适当的双重检查锁定代码)。
synchronized (Singleton.class) {
Singleton value = singleton;
if (singleton == null) {
value = new Singleton();
singleton = value;
}
return value;
}

not thread-safe because of the return singleton outside the synchronized block


由于您使用的是 synchronized block ,这不是问题。双重检查锁定就是试图避免 synchronized正如您指出的那样,阻止在每个操作中被击中。

all the threads running within the synchronized block will force a happen-before relation (i.e., there is no way threads will return null if the instance was properly set) Or am I wrong?


这是正确的。你没有错。

However, that can be simply because performance-wise it is the same since threads have to synchronized away, so why not be on the safe side and put the return inside?!.


没有理由不这样做,尽管我认为“安全方面”更多的是在其他人查看此代码并在将来担心它时引起惊愕,而不是从语言定义的角度来看“更安全”。再次,如果有其他地方 singleton然后分配 return应该在 synchronized 内堵塞。

关于java - 在线程安全单例中,返回是否必须在同步块(synchronized block)内,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66663482/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com