Nic*_*tch 4 c# singleton multithreading
我在多线程环境中有一个高吞吐量的Singleton.通常我会做这样的事情:
public static Foo GetInstance()
{
lock (Foo._syncLock)
{
if (Foo._instance == null)
Foo._instance = new Foo();
return Foo._instance;
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道如果执行以下操作会更有效率,因为它会避免连续的线程锁定,或者是否存在隐藏的问题?
public static Foo GetInstance()
{
if (Foo._instance != null)
return Foo._instance;
lock (Foo._syncLock)
{
if (Foo._instance == null)
Foo._instance = new Foo();
return Foo._instance;
}
}
Run Code Online (Sandbox Code Playgroud)
我想知道如果执行以下操作会更有效率,因为它会避免连续的线程锁定,或者是否存在隐藏的问题?
你的问题是"通过采用危险的低锁模式会有性能提升吗?" 这是一个完全错误的问题.永远不要这样说!这种方式浪费时间,浪费精力,以及疯狂,不可能调试的错误.
正确的问题是"我的测量结果是否强烈表明我开始时遇到性能问题? ".
如果答案是"不",那么你就完成了.
只有当答案为"是"时,你才应该问下一个问题,即" 我可以通过消除对锁的争用来消除我的性能问题吗? "
如果答案为"是",则消除对锁的争用并返回第一个问题.
只有当答案是"否"时,你应该问下一个问题,即" 将采用低锁定解决方案给出可接受的性能吗?"
请注意,对于此问题的答案为"是",您必须处于这样的情况:非竞争锁定施加的十纳秒惩罚是您的表现的门控因素.很少有人处于10或20纳秒太长的位置.
在极不可能的事件中,答案是肯定的,你应该继续讨论下一个问题,即" 双重检查锁定的正确实现是否会消除我的性能问题? "
如果双重检查锁定不够快,那么实现它是一个非启动器.你必须以其他方式解决你的问题.
只有当问题的答案为"是"时,才应实施双重检查锁定.
现在让我们来看看你的实际问题:
它有隐藏的问题吗?
您的实施是正确的.然而,当你偏离幸福的模式时,所有的赌注都会被取消.例如:
static object sync = new object();
static bool b = false;
static int x = 0;
static int GetIt()
{
if (!b)
{
lock(sync)
{
if (!b)
{
b = true;
x = ExpensiveComputation();
}
}
}
return x;
}
Run Code Online (Sandbox Code Playgroud)
看起来是对的,对吧?但这不正确!考虑低锁路径.由于此路径上没有障碍,x的值可以在一个线程上预取为零,然后另一个线程可以运行并将b设置为true,将x设置为123,然后原始线程可以获取b,get是的,并返回预取的x.
那么解决方案是什么?根据我的偏好顺序,它们是:
Lazy<T>.InterlockedCompareExchange.| 归档时间: |
|
| 查看次数: |
410 次 |
| 最近记录: |