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)
首先,我需要说明一些假设:
有一个很好的理由我不能只是一个应用程序启动时这样做.也许数据还没有,等等.
Foo可以被实例化并且从两个或更多个线程同时使用.我希望其中一个最终创建一些数据(但不是两个)然后我将允许两者访问相同的数据(忽略访问数据的线程安全性)
SomeDataDoesNotExist()的成本并不高.
现在,这不一定要局限于某些数据创建情况,但这是我能想到的一个例子.
我特别感兴趣的是识别模式的部分是check - > lock - > check.我不得不在一些情况下向开发人员解释这种模式,他们乍看之下没有得到算法,但可以欣赏它.
无论如何,其他人必须做同样的事情.这是标准化模式吗?它叫什么?
Eri*_*ert 13
虽然我可以看到你怎么认为这看起来像双重检查锁定,它实际上看起来是危险的破坏和不正确的双重检查锁定.如果没有SomeDataDoesNotExist和CreateSomeData的实际实现来批评,我们无法保证这个东西在每个处理器上实际上都是线程安全的.
有关双重检查锁定可能出错的分析示例,请查看此双重检查锁定的错误和错误版本:
我的建议:如果没有令人信服的理由,请不要使用任何低锁技术,也不要使用内存模型专家的代码审查; 你可能会弄错.大多数人这样做.
特别是,不要使用双重检查锁定,除非您可以准确描述处理器可以代表您执行的内存访问重新排序,并提供令人信服的论据,即在任何可能的内存访问重新排序的情况下,您的解决方案是正确的.在你从一个已知的正确实现中稍微离开的那一刻,你需要从头开始分析.你不能假设只是因为双重检查锁定的一个实现是正确的,它们都是; 几乎没有一个是正确的.
使用双重检查锁定进行延迟初始化?
| 归档时间: |
|
| 查看次数: |
924 次 |
| 最近记录: |