这种模式的名称?(答案:使用双重检查锁定进行延迟初始化)

Mat*_*und 1 c# java design-patterns

请考虑以下代码:

public class Foo
{
    private static object _lock = new object();

    public void NameDoesNotMatter()
    {
        if( SomeDataDoesNotExist() )
        {
            lock(_lock)
            {
                if( SomeDataDoesNotExist() )
                {
                    CreateSomeData();
                }
                else
                {
                    // someone else also noticed the lack of data.  We
                    // both contended for the lock.  The other guy won
                    // and created the data, so we no longer need to.
                    // But once he got out of the lock, we got in.
                    // There's nothing left to do.
                }
            }
        }
    }

    private bool SomeDataDoesNotExist()
    {
        // Note - this method must be thread-safe.
        throw new NotImplementedException();
    }

    private bool CreateSomeData()
    {
        // Note - This shouldn't need to be thread-safe
        throw new NotImplementedException();
    }
}
Run Code Online (Sandbox Code Playgroud)

首先,我需要说明一些假设:

  1. 有一个很好的理由我不能只是一个应用程序启动时这样做.也许数据还没有,等等.

  2. Foo可以被实例化并且从两个或更多个线程同时使用.我希望其中一个最终创建一些数据(但不是两个)然后我将允许两者访问相同的数据(忽略访问数据的线程安全性)

  3. SomeDataDoesNotExist()的成本并不高.

现在,这不一定要局限于某些数据创建情况,但这是我能想到的一个例子.

我特别感兴趣的是识别模式的部分是check - > lock - > check.我不得不在一些情况下向开发人员解释这种模式,他们乍看之下没有得到算法,但可以欣赏它.

无论如何,其他人必须做同样的事情.这是标准化模式吗?它叫什么?

Eri*_*ert 13

虽然我可以看到你怎么认为这看起来像双重检查锁定,它实际上看起来是危险的破坏和不正确的双重检查锁定.如果没有SomeDataDoesNotExist和CreateSomeData的实际实现来批评,我们无法保证这个东西在每个处理器上实际上都是线程安全的.

有关双重检查锁定可能出错的分析示例,请查看此双重检查锁定的错误和错误版本:

C#手动锁定/解锁

我的建议:如果没有令人信服的理由,请不要使用任何低锁技术,也不要使用内存模型专家的代码审查; 你可能会弄错.大多数人这样做.

特别是,不要使用双重检查锁定,除非您可以准确描述处理器可以代表您执行的内存访问重新排序,并提供令人信服的论据,即在任何可能的内存访问重新排序的情况下,您的解决方案是正确的.在你从一个已知的正确实现中稍微离开的那一刻,你需要从头开始分析.你不能假设只是因为双重检查锁定的一个实现是正确的,它们都是; 几乎没有一个是正确的.

  • @Matthew:SomeDataDoesNotExist是否是线程安全无关紧要; 我的意思是,是的,它必须是线程安全的,但它需要不止于此.*整个模式*需要是线程安全的**,在这个世界中,从多个处理器**可以任意重新排序不同地址的读取.这是一个比单纯的线程安全更深刻,更复杂的要求! (2认同)
  • @ Pure.Krome:非常普通的锁定.*低锁技术很危险.*避免它们.拿锁; 它可能足够快. (2认同)

Ben*_*igt 9

使用双重检查锁定进行延迟初始化?

  • 正是.顺便说一句,.NET 4提供了一个非常好的`Lazy`类来处理Lazy初始化的实现细节.有关示例,请参阅http://stackoverflow.com/questions/5986466/why-use-system-runtime-caching-or-system-web-caching-vs-static-variables/5986819#5986819. (2认同)