![]() |
1
13
在本例中,异常1几乎立即在我的机器上抛出:
但是,不设计为线程安全的代码的确切行为是
不可预知的
.
不过,我不确定是否要进行单元测试,因为测试并发代码(并使其正确)比首先编写并发代码要复杂得多。 |
![]() |
2
20
显然,代码不是threadsafe。我们这里有一个明确的案例,说明了过早优化的危害。 记住,双重检查锁定模式的目的是 提高性能 通过消除锁的成本来消除代码。如果锁是未经检验的,那么它已经非常便宜了。因此,只有在以下情况下,双重检查的锁定模式才是合理的:(1)在锁将受到严重竞争的情况下,或(2)在代码如此的情况下 难以置信地 性能敏感,未经测试的锁的成本仍然过高。 显然,我们不是第二种情况。你在用字典看在上帝的份上。即使没有锁,它也会进行查找和比较,这比避免未经测试的锁节省的成本高出数百或数千倍。 如果我们是第一个病例,那么 找出引起争用的原因并消除 . 如果你在等待一个锁的时候做了很多事情,那么就找出原因,用一个瘦的读写器锁替换这个锁,或者重新构造应用程序,这样就不会有那么多线程同时攻击同一个锁。 在这两种情况下,都没有理由进行危险的、对实现敏感的低锁技术。您应该只在那些非常罕见的情况下使用低锁技术,在这些情况下,您真的,真的不能承担未经测试的锁的成本。 |
![]() |
3
8
我真的不认为你
需要
为了证明这一点,你只需要让人们
documentation for
这实际上是一个众所周知的事实(或者应该是),当另一个线程正在向字典写入时,您不能从字典中读取数据。我在这里看到了一些“奇怪的多线程问题”类型的问题,所以作者没有意识到这是不安全的。 这个问题与双重检查锁定没有特别的关系,只是字典不是线程安全类,甚至对于单个编写器/单个读卡器场景也是如此。 我会更进一步,告诉你为什么在Reflector中,这不是线程安全的:
看看如果
这正是DTB例子中失败的地方。线程A搜索的键是
预先知道
在字典里,却找不到。为什么?因为
故事的寓意:
事实上,由于抖动和CPU、陈旧的缓存等指令重新排序,问题实际上比这要严重得多——这里没有任何内存障碍——但这应该证明
毫无疑问
如果你有一个
|
![]() |
4
3
我想这个问题反复出现的原因是:
为什么?
|
![]() |
5
1
包括问题中的代码,您可以使用以下代码对其进行测试。
这个程序只是试图
添加这个测试是很困难的,因为它是一个概率测试,而且你不知道失败需要多长时间(如果有)。我想你可以选择一个10秒的值,让它运行那么长时间。如果在这段时间内没有失败,那么测试就通过了。不是最好的,而是一些东西。您还应该验证
|