单身人士Java中的多线程

单身人士Java中的多线程

问题描述:

在多线程环境中使用Singleton类的首选方式是什么?

What is the preferred way to work with Singleton class in multithreaded environment?

假设我有3个线程,并且都尝试访问 getInstance()同时处理单例类的方法 -

Suppose if I have 3 threads, and all of them try to access getInstance() method of singleton class at the same time -


  1. 如果没有同步,会发生什么保持?

  2. 使用 synchronized getInstance()方法或使用同步块内 getInstance()

  1. What would happen if no synchronization is maintained?
  2. Is it good practice to use synchronized getInstance() method or use synchronized block inside getInstance().

请指示是否有其他出路。

Please advise if there is any other way out.

这个任务在理论上是不平凡的,因为你想让它真正的线程安全。

The task is non-trivial in theory, given that you want to make it truly thread safe.

一篇非常好的论文被发现 @ IBM

A very nice paper on the matter is found @ IBM

只需获得单例就不需要任何同步,因为它只是一个阅读。所以,只是syncrhonize同步的设置将做。除非两个尝试在同一时间启动时创建单例,那么您需要确保检查实例是否设置了两次(一个在外部和同步之间),以避免在最坏的情况下重置该实例。

Just getting the singleton does not need any sync, since it's just a read. So, just syncrhonize the setting of the Sync would do. Unless two treads try to create the singleton at start up at the same time, then you need to make sure check if the instance is set twice (one outside and one inside the sync) to avoid resetting the instance in a worst case scenario.

然后,您可能需要考虑JIT编译器如何处理无序写入。这个代码将会有些接近解决方案,虽然不会100%线程安全:

Then you might need to take into account how JIT compilers handle out-of-order writes. This code will be somewhat near the solution, although won't be 100% thread safe anyway:

public static Singleton getInstance() {
    if (instance == null) {
        synchronized(Singleton.class) {      
            Singleton inst = instance;         
            if (inst == null) {
                synchronized(Singleton.class) {  
                    instance = new Singleton();               
                }
            }
        }
    }
    return instance;
}

所以,你应该不喜欢懒惰的东西:

So, you should perhaps resort to something less lazy:

class Singleton {
    private static Singleton instance = new Singleton();

    private Singleton() { }

    public static Singleton getInstance() {
        return instance;
    }
}

或者,有点blo肿,但更灵活方法是避免使用静态单身人士,并使用注册框架,例如 Spring 来管理singleton-ish的实例化对象(您可以配置延迟初始化)。

Or, a bit more bloated, but a more flexible way is to avoid using static singletons and use an injection framework such as Spring to manage instantiation of "singleton-ish" objects (and you can configure lazy initialization).