Interlocked.CompareExchange“短路”评估

时间:2015-08-20 12:20:38

标签: c# .net task-parallel-library

我刚刚意识到我在Interlocked.CompareExchange中分配了很多对象并将它们扔给GC,因为与&&或{{1}相比,总是会评估值(第二个参数) },使用short-circuit evaluation

锁定是原子检查null的唯一替代方法,仅当目标位置为||时才分配新对象吗?

此测试打印“我已创建”三次,并在最后一次断言时失败。

null

在我的真实代码中,我使用internal class TestCompareExchange { public static TestCompareExchange defalt = new TestCompareExchange(); public static bool allocated = false; public TestCompareExchange() { allocated = true; Console.WriteLine("I am created"); } } [Test] public void CompareExchangeAllocatesValue() { if (TestCompareExchange.allocated && (new TestCompareExchange()) != null) // the second part after && is not evaluated { } Assert.IsFalse(TestCompareExchange.allocated); TestCompareExchange target = null; var original = Interlocked.CompareExchange(ref target, new TestCompareExchange(), (TestCompareExchange)null); Assert.AreEqual(null, original); Assert.IsTrue(TestCompareExchange.allocated); TestCompareExchange.allocated = false; target = null; original = Interlocked.CompareExchange(ref target, new TestCompareExchange(), TestCompareExchange.defalt); Assert.AreEqual(null, original); Assert.IsFalse(TestCompareExchange.allocated); // no exchange, but objetc is allocated } 而不是假对象。有关系吗?是否存在一些TCS对象的池,这使得分配和集合与它们无关?

1 个答案:

答案 0 :(得分:3)

在执行Interlocked操作和分配之前,请查看目标位置是否已为空。如果是,则无需尝试初始化它。

if (Volatile.Read(ref target) == null) InitAtomically();