gpt4 book ai didi

java - 改变一下单例模式

转载 作者:行者123 更新时间:2023-12-02 13:56:12 24 4
gpt4 key购买 nike

这是一个求职面试问题。

Implement the singleton pattern with a twist. First, instead of storing one instance, store two instances. And in every even call of getInstance(), return the first instance and in every odd call of getInstance(), return the second instance.

我的实现如下:

public final class Singleton implements Cloneable, Serializable {
private static final long serialVersionUID = 42L;
private static Singleton evenInstance;
private static Singleton oddInstance;
private static AtomicInteger counter = new AtomicInteger(1);

private Singleton() {
// Safeguard against reflection
if (evenInstance != null || oddInstance != null) {
throw new RuntimeException("Use getInstance() instead");
}
}

public static Singleton getInstance() {
boolean even = counter.getAndIncrement() % 2 == 0;
// Make thread safe
if (even && evenInstance == null) {
synchronized (Singleton.class) {
if (evenInstance == null) {
evenInstance = new Singleton();
}
}
} else if (!even && oddInstance == null) {
synchronized (Singleton.class) {
if (oddInstance == null) {
oddInstance = new Singleton();
}
}
}

return even ? evenInstance : oddInstance;
}

// Make singleton from deserializaion
protected Singleton readResolve() {
return getInstance();
}

@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("Use getInstance() instead");
}
}

你发现问题了吗?第一次调用可能会进入 getInstance 并且线程被抢占。第二次调用可能会输入 getInstance,但会获取 oddInstance 而不是 evenInstance

显然,可以通过使 getInstance 同步来防止这种情况,但这是不必要的。在单例的生命周期中只需要两次同步,而不是每次 getInstance 调用都需要同步。

想法?

最佳答案

最重要的是,evenInstanceoddInstance 变量需要声明为 volatile。请参阅著名的“双重检查锁定已损坏”声明:https://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

此外,您确实应该在偶数实例和奇数实例的同步块(synchronized block)中使用不同的对象,以便可以同时构造它们。

最后,Singleton 构造函数中的检查被破坏,并且将在第二次调用 getInstance() 时抛出异常

除此之外还可以,但是如果您自己不进行并发工作会更好:

public final class Singleton implements Cloneable, Serializable {
private static AtomicInteger counter = new AtomicInteger(1);


public static Singleton getInstance() {
if (counter.getAndIncrement() % 2 == 0) {
return EvenHelper.instance;
} else {
return OddHelper.instance;
}
}

private static class EvenHelper {
//not initialized until the class is used in getInstance()
static Singleton instance = new Singleton();
}

private static class OddHelper {
//not initialized until the class is used in getInstance()
static Singleton instance = new Singleton();
}
}

关于java - 改变一下单例模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56829866/

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