Singleton中的线程安全性 [英] Thread safety in Singleton

查看:219
本文介绍了Singleton中的线程安全性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我所知,Java中的双重锁定已被破坏,那么在Java中使单例线程安全的最佳方法是什么?我想到的第一件事是:

I understand that double locking in Java is broken, so what are the best ways to make Singletons Thread Safe in Java? The first thing that springs to my mind is:

class Singleton{
    private static Singleton instance;

    private Singleton(){}

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

这有用吗?如果是这样,它是最好的方式(我想这取决于具体情况,所以说明特定技术最好的时候会很有用)

Does this work? if so, is it the best way (I guess that depends on circumstances, so stating when a particular technique is best, would be useful)

推荐答案

Josh Bloch建议使用单元素枚举类型来实现单例(请参阅 Effective Java 2nd Edition,第3项:使用私有实现单例属性构造函数或枚举类型)。

Josh Bloch recommends using a single-element enum type to implement singletons (see Effective Java 2nd Edition, Item 3: Enforce the singleton property with a private constructor or an enum type).

有些人认为这是一个黑客,因为它没有明确传达意图,但它确实有效。

Some people think this is a hack, since it doesn't clearly convey intent, but it does work.

以下示例直接来自本书。

The following example is taken straight from the book.

public enum Elvis {
   INSTANCE;

   public void leaveTheBuilding() { ... }
}

这是他的结论:


这种方法更简洁,免费提供序列化机制,并提供即使面对复杂的序列化或反射攻击,也是对多个实例的坚定保证。虽然这种方法尚未被广泛采用,但单元素枚举类型是实现单例的最佳方式。






On enum 常数单身保证



< a href =http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.9 =noreferrer> JLS 8.9。枚举




On enum constant singleton guarantee

JLS 8.9. Enums


枚举类型没有除其枚举常量定义的实例之外的实例。尝试显式实例化枚举类型(第15.9.1节)是编译时错误。

An enum type has no instances other than those defined by its enum constants. It is a compile-time error to attempt to explicitly instantiate an enum type (§15.9.1).

最终克隆 c>枚举中的$ c>方法确保永远不会克隆枚举常量,并且序列化机制的特殊处理可确保不会因反序列化而创建重复实例。禁止对枚举类型进行反射实例化。总之,这四件事确保除了枚举常量定义的枚举类型之外不存在枚举类型的实例。

The final clone method in Enum ensures that enum constants can never be cloned, and the special treatment by the serialization mechanism ensures that duplicate instances are never created as a result of deserialization. Reflective instantiation of enum types is prohibited. Together, these four things ensure that no instances of an enum type exist beyond those defined by the enum constants.






在延迟初始化



以下片段:


On lazy initialization

The following snippet:

public class LazyElvis {
    enum Elvis {
        THE_ONE;
        Elvis() {
            System.out.println("I'M STILL ALIVE!!!");
        }       
    }
    public static void main(String[] args) {
        System.out.println("La-dee-daaa...");
        System.out.println(Elvis.THE_ONE);
    }
}

产生以下输出:

La-dee-daaa...
I'M STILL ALIVE!!!
THE_ONE

如您所见, THE_ONE 常量在第一次访问时不会通过构造函数实例化。

As you can see, THE_ONE constant is not instantiated through the constructor until the first time it's accessed.

这篇关于Singleton中的线程安全性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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