gpt4 book ai didi

c# - 这个多线程Singleton是不是更高效?

转载 作者:太空狗 更新时间:2023-10-30 00:24:55 25 4
gpt4 key购买 nike

我在多线程环境中有一个高吞吐量的单例。通常我会做这样的事情:

public static Foo GetInstance()
{
lock (Foo._syncLock)
{
if (Foo._instance == null)
Foo._instance = new Foo();
return Foo._instance;
}
}

我想知道是否改为执行以下操作会更有效,因为它可以避免持续的线程锁定,或者它是否存在隐藏的问题?

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;
}
}

最佳答案

I'm wondering if doing the following instead would be more efficient since it would avoid the continual thread locking, or are there hidden problems with it?

您的问题是“采用危险的低锁模式是否会提高性能?”这是完全错误的问题。永远不要这样推理!那就是浪费时间、浪费精力和疯狂的、无法调试的错误。

正确的问题是“我的测量是否强烈表明我一开始就有性能问题?”。

如果答案是“否”,那么您就完成了。

只有当答案为"is"时,您才应该问下一个问题,即“我可以通过消除锁争用来消除我的性能问题吗?

如果答案是"is",则消除对锁的争用并返回第一个问题。

只有当答案为“否”时,您才应该问下一个问题,即“采用低锁解决方案是否会提供可接受的性能?”

请注意,要使此问题的答案为"is",您必须处于这样一种情况:无竞争锁强加的 10 纳秒惩罚是您性能的门控因素。 很少有人认为十或二十纳秒太长。

在答案为"is"的极不可能的情况下,您应该继续下一个问题,即“正确实现双重检查锁定是否可以消除我的性能问题?

如果双重检查锁定不够快,那么实现它是行不通的。您必须以其他方式解决您的问题。

只有当该问题的答案为"is"时,您才应该实现双重检查锁定。

现在让我们来回答您的实际问题:

are there hidden problems with it?

您的实现是正确的。然而,一旦你偏离了幸福的模式,所有的赌注都会落空。例如:

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;
}

这看起来是正确的,对吧?但这是不正确的!考虑低锁路径。由于这条路径上没有障碍,x的值可以在一个线程上预取为零,然后另一个线程可以运行并将b设置为true,x设置为123,然后原始线程可以获取b,得到true,并返回预取的 x。

那么解决方案是什么?在我的偏好顺序中,它们是:

  • 不要偷懒。初始化静态字段一次并完成它。
  • 使用 Jon Skeet 网站上记录的 blessed lazy singleton 模式。
  • 使用Lazy<T> .
  • 使用单一检查锁定。
  • 如果您不关心单例是否在极少数情况下创建两次并丢弃一次,请使用 InterlockedCompareExchange .
  • 使用有福的双重检查锁定模式。

关于c# - 这个多线程Singleton是不是更高效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20688748/

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