以下 java 代码线程安全没有 volatile 吗? [英] Is the following java code thread safe without volatile?

查看:76
本文介绍了以下 java 代码线程安全没有 volatile 吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

public static Singleton singleton;

public static Singleton get(){
    synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
    } 
    return singleton;
}

有人说 singleton 变量没有 volatile 是错误的.但我认为这是创建单例对象的正确代码.我想知道这段代码有没有线程安全?

Some one say that no volatile for singleton variable is wrong. But I think this is the right code for singleton object creation. I want to know whether this code has a thread safety or not?

推荐答案

正如 anatolyg 指出的那样,您应该使字段 singleton 私有以避免对该字段进行不必要的非线程安全访问.

As anatolyg pointed out, you should make the field singleton private to avoid unwanted non-thread-safe accesses to that field.

此外,即使在:

public static Singleton get(){
    synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
    } 
    return singleton;
} 

return singleton;synchronized 块之外,这段代码仍然是线程安全的,因为剩余的代码在 synchronized 块之外code>synchronized 块,因此,该块中的所有线程将强制 happens-before 关系(,如果实例设置正确).

the return singleton; is outside of the synchronized block, this code is still thread-safe because the remaining code is inside the synchronized block, and consequently, all threads within that block will force a happens-before relation (i.e., there is no way threads will return null if the instance was properly set).

据说要注意:引用 Holger

只要实际写入单例发生-在开始之前同步块,一切正常.它只工作因为最多有一次写入,肯定在写入之前执行返回.如果可以进行更多写入,则它们可以同时发生到同步块之外的 return 语句.

As long as the actual write to singleton happens-before the beginning of the synchronized block, everything works. It only works because there is at most one write, definitely performed before the return. If more writes were possible, they could happen concurrently to the return statement that is outside the synchronized block.

有一个完整的SO 线程 解决了为什么将 return singleton 留在 synchronized 块之外是线程安全的.

There is a complete SO Thread that tackles why it is thread-safe to leave the return singleton outside the synchronized block.

尽管如此,我与其他用户(例如这个

Notwithstanding, I share the same opinion of others users such as this one

因为返回不占用任何CPU或任何东西,所以没有理由为什么它不应该在同步块内.如果当时如果我们在单例中,该方法可以被标记为同步在这里上课.如果单身人士得到,这将更清洁和更好在别处修改.

since the return doesn't take any CPU or anything, there is no reason why it shouldn't be inside of the synchronized block. If it was then the method can be marked as synchronized if we are in the Singleton class here. This would be cleaner and better in case singleton gets modified elsewhere.

也就是说,您不需要 volatile 子句,因为您正在同步变量 singleton 的初始化.在这种情况下,synchronized 子句不仅保证多个线程不会访问:

That being said you don't need the volatile clause because you are synchronizing the initialization of the variable singleton. In this context, the synchronized clause guarantees not only that multiple threads will not access:

    if (singleton == null) {  
        singleton = new Singleton();  
    }  

而且每个线程都会看到 singleton 字段的最新参考.因此,不会发生多个线程将不同对象实例分配给 singleton 字段的竞争条件.

but also that each thread sees the most up-to-date reference of the singleton field. Consequently, the race-condition of multiple threads assigning different object instances to the singleton field will not happen.

有人说单例变量没有 volatile 是错误的.

Some one say that no volatile for singleton variable is wrong.

可能此人将您的代码误认为是 双重检查锁定模式,这是对您显示的版本的性能优化.在您的版本中,线程将在每次调用 get 方法时进行同步,这在变量 singleton 正确初始化后没有必要.这是双重检查锁定模式试图避免的开销.为了实现这一点,需要 volatile(您可以阅读有关此 SO 线程),可以在 此处.

Probably this person is mistaken your code with the double-checked locking pattern, which is a performance optimization over the version that you have shown. In your version threads will synchronize every time they call the method get, which is not necessary after the variable singleton has been correctly initialized. This is the overhead that the double-checked locking pattern tries to avoid. To achieve that the volatile is needed (you can read an in-depth explanation on this SO Thread), more information about this double-checked locking pattern can be found here.

这篇关于以下 java 代码线程安全没有 volatile 吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆