如果参数化,按需初始化持有人习惯仍然安全吗? [英] Is initialization-on-demand holder idiom still safe if parameterized?

查看:43
本文介绍了如果参数化,按需初始化持有人习惯仍然安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我修改了股票按需初始化持有人惯用法示例像这样:

public class Something {

    //internal params, unchangeable after the initialization
    private final List<String> params;

    //changeable params that will be used for initialization
    private final static List<String> initParams = new ArrayList<>();

    private Something(List<String> params) {
        this.params = params;
    }

    //allow params to be added prior to initialization
    public static void addParam(String param) {
        initParams.add(param);
    }

    private static class LazyHolder {
        static final Something INSTANCE =
            new Something(Collections.unmodifiableList(initParams));
    }

    public static Something getInstance() {
        return LazyHolder.INSTANCE;
    }

    public int calculate() {
       return params.size(); //use the internal params somehow
    }
}

并按如下方式使用:

  • 只有1个线程多次调用 addParam 来准备初始化(唯一的 writing 线程)
  • 许多线程(可能是在 writing 线程之前创建的)稍后调用 getInstance 以获得单例实例(许多 reading 线程)
  • getInstance 的初始调用可以由 writing 线程或 reading 线程之一
  • 执行
  • Only 1 thread calls addParam multiple times to prepare the initialization (the only writing thread)
  • Many threads (that may have been created before the writing thread) later call getInstance to obtain the singleton instance (many reading threads)
  • The initial call to getInstance could be performed by either the writing thread or one of the reading threads

这种用法是否安全(尽管令人费解)?
根据哪个线程(读取器或写入器)首先调用 getInstance ,有什么变化吗?
如果将静态 initParams 变量设置为 volatile ,会发生变化吗?

Is this usage safe (albeit convoluted)?
Does anything change depending on which thread (reader or writer) first calls getInstance?
Does anything change if the static initParams variable is made volatile?

如果第一次调用是由 reading 线程(在 writing 线程之前创建的)执行的,则其 initParams 的内部视图是否过时?并导致初始化的实例也过时了?

If the first call is performed by a reading thread (created before the writing thread), can its internal view of initParams be outdated and cause the initialized instance to be outdated as well?

推荐答案

这种用法是否安全(尽管令人费解)?

Is this usage safe (albeit convoluted)?

不,在目前所说的问题中,我认为您没有任何保证,第一次调用 getInstance 会发生-在最后一次调用 addParam .

No, I don't think you have any guarantees, in the question as currently stated, that the first call to getInstance will happen-after the last call to addParam.

您确实说过第一次调用 getInstance 会在以后"发生,但是您可以这样说:"[[读者线程]可能是在编写线程之前创建的",从而限定了该条件.让我认为您不能保证此订单.

You do say that the first call to getInstance will happen "later", but you then qualify that by saying that "[the reader threads] may have been created before the writing thread", which makes me think that you can't guarantee this order.

如果您可以保证init和读取之间的这种后发生"关系,那么我认为这是线程安全的,是的,出于更简单版本的原因.

If you can guarantee this "happens-after" relation between the init and the reads, then I think this is thread safe, yes, for the same reason that the simpler version is.

根据哪个线程(读取器或写入器)首先调用getInstance进行任何更改吗?

Does anything change depending on which thread (reader or writer) first calls getInstance?

是的,如果编写者线程是第一个调用 getInstance 的线程,那么事情应该是线程安全的.那是因为它保证了对全局变量 initParams 的写操作发生-在以后在同一线程上读取之前.

Yes, if the writer thread is the first to call getInstance, then things should be thread-safe. That is because its writes to the global variable initParams are guaranteed to happen-before later reads on the same thread.

但是,这基本上与我上面讨论的相同,所以我认为这只是在四处移动.

However, this is basically the same guarantee I discussed above, so I think this is just moving things around.

如果将静态initParams变量设置为volatile,有什么改变吗?

Does anything change if the static initParams variable is made volatile?

这将有助于缩小第一次调用 getInstance 和最后一次调用 addParam 之间的竞争,但是我认为您仍然依赖于后者发生在之后前者.

That would help to narrow the race between the first call to getInstance and the last call to addParam, but I think you are still relying on the latter happening "after" the former.

此设计脆弱,复杂且丑陋.您正在使用全局变量" initParams ",并依赖于一些非常棘手的副作用和排序.

This design is fragile, complex and ugly. You are using a global variable "initParams" and relying on some very tricky side-effects and ordering.

您说您有一个构建"Something"实例的"writer thread",并且稍后"将被读取.

You say that you have a "writer thread" which builds up the "Something" instance and that "later" it will be read.

您是否可以不重新安排内容,以便所有写作都严格在阅读开始之前进行,并完全停止使用静态变量?

Can you not re-arrange things so that all the writing happens strictly before the reading starts, and stop using static variables entirely?

这篇关于如果参数化,按需初始化持有人习惯仍然安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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