Interlocked.CompareExchange"short-circuit"评价

Interlocked.CompareExchange "short-circuit" evaluation

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

只有当目标位置为 null 时,锁是原子检查 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 对象池使得分配和收集与它们无关?

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

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