7

所以这是我用于双重检查锁定的自定义实用程序:它是一种静态方法,您可以将标准、同步对象和要执行的操作输入其中。

public static bool RunIf(Func<bool> criterion, object syncObject, Action action)
{
    if (criterion())
        lock(syncObject)
            if (criterion())
            {
                Thread.MemoryBarrier(); 
                action();
                return true;
            }
    return false;
}

我了解到,根据 C# 规范,优化器可以重新排序内存分配,在没有内存屏障的情况下,这种技术可以给出误报并在不应该执行操作时执行操作。

在我的小世界里,如果这样的失败是可能的,那么也应该可以设计一个测试,通过使用足够数量的并行测试用例对场景进行足够猛烈的冲击,从而始终如一地证明失败。我一直在寻找这样的测试大约一年了,但到目前为止我还是一片空白。谁能给我看一个测试:

  1. 显示此方法在没有内存屏障的情况下失败;

  2. 在恢复内存屏障的情况下重复测试时显示其成功?

4

2 回答 2

1

不,不可能测试非确定性行为(或者至少,如果你这样做了,那么否定结果仍然是不确定的)。

于 2013-06-16T00:48:05.110 回答
0

不可能构建这样的测试,因为“lock”语句已经为锁定的指令块创建了一个完整的栅栏(即获取和释放栅栏)。因此,附加Thread.MemoryBarrier()是多余的,没有任何作用。

因此,根据传入的委托的criterion作用,您的RunIf构造本身要么是安全的,要么是完全多余的。

我的意思是,如果传入的criterion委托从可变状态派生其返回值,并且该可变状态不受相同的保护(直接或间接),则syncObject此代码不安全并且RunIf基本上没有任何效果除了criterion用完整的栅栏包围在对代表的第二次调用中执行的指令。

于 2013-07-14T01:17:23.193 回答