联锁.CompareExchange“short-circuit"评估

本文关键字:quot 评估 short-circuit CompareExchange 联锁 | 更新日期: 2023-09-27 18:08:50

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

如果目标位置是null,那么lock是自动检查null并分配新对象的唯一选择吗?

这个测试打印"I am created"三次,在最后一个断言时失败。

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
}
在我的实际代码中,我使用TaskCompletionSource而不是假对象。这有关系吗?是否存在一些TCS对象池,使得分配和收集与它们无关?

联锁.CompareExchange“short-circuit"评估

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

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