- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我在多线程环境中有一个高吞吐量的单例。通常我会做这样的事情:
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。
那么解决方案是什么?在我的偏好顺序中,它们是:
Lazy<T>
.InterlockedCompareExchange
. 关于c# - 这个多线程Singleton是不是更高效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20688748/
此处,“OK”当然意味着 AYOR(风险由您自己承担),但如果避免与现有属性名称发生明显冲突,则不会出现可预见的问题。 Skyfield物体——尤其是行星——通常具有有限数量的属性。我经常编写简短的脚
我们有一个(假设)将在 1-2 年内完成的项目。到那时,JDK7(希望还有 Java7 JCP 规范)应该准备就绪。 但是,我想知道,甲骨文做出“愚蠢”决定的“危险”有多大,这会使 JDK7 成为一个
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 6 年前。 Improv
要知道,haswell是英特尔作为Ivy Bridge微架构的“第四代核心”继承者而开发的一种处理器微架构的代号。 1英特尔正式发布了基于这种微架构的CPU... More 但是,我想知道如何通过在
修改 setter 参数是否正常?假设我们有 setString 方法。我们真的想保留字符串的修剪形式。所以带有尾随空格的字符串是无效的,但我们不想抛出异常。 最好的解决办法是什么?修剪 setter
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 去年关闭。 Improve this
我写了一段代码,然后编译它没有错误。但是当我运行时,它会引发异常(java.lang.NoClassDefFoundError: TesKt$test$1$1)。 这是语言错误吗? private f
这道题是从算法导论的习题23.1-7演化而来的。 原问题是: 23.1-7争论如果一个图的所有边权重都是正的,那么连接所有顶点并且具有最小总权重的边的任何子集必须是一棵树。举例说明,如果我们允许某些权
假设我创建了一个 lambda 实例,稍后我想查询该对象以查看它是 proc 还是 lambda。如何做到这一点? .class() 方法不起作用。 irb(main):001:0> k = lamb
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
所以我正在将我的一个程序移植到一个新的游戏机上。问题是用于编译我的 c++ 应用程序的 SDK 不支持 __int16,但它支持 int16_t。使用 int16_t 代替 __int16 是否“安全
我最近偷看了 Url.IsLocalUrl() 方法的实现,该方法被广泛使用并被推荐为用于防止重定向攻击的措施之一。我惊讶地发现,如果我要为我的应用程序中的 Controller 的其中一个操作提供完
我读了这篇好文章 Angular onPush Change Detection Strategy 在某个时候他写道: It’s an anti-pattern to expose your subj
我是这样理解的: Innodb 中的缓冲池:它存储来自 Sql 表的索引和数据并缓存它以供将来查询,因此它不需要一直打扰 Mysql。 Memcached:用于存储从 Innodb 接收到的数据并对其
以防万一 vector 为空,(意外,异常(exception)情况) cppreference 在 vector::back() 上说: Calling back on an empty conta
我是一名优秀的程序员,十分优秀!