C#等待计数器值失败

本文关键字:失败 计数器 等待 | 更新日期: 2023-09-27 18:29:47

我有一段代码,它使用回调来修改其他线程的计数器值。我对它使用lock,并使用empty while循环来检查计数器是否==0。它在Visual Studio中运行时工作得很好。然而,在"释放"它并从二进制文件运行之后,它就冻结了。while循环以及回调方法主体如下所示。

是什么原因造成的?

谢谢,

public void someMethod() {
 //starting a bunch of threads calling the callback method
    while(counter > 0) {}
}
public void Callback()
    {
        lock (this)
        {
            countdown--;
        }
    }

C#等待计数器值失败

每次访问线程之间共享的变量时,都需要锁,而不仅仅是在一个位置。在这种情况下,while循环中的代码在访问counter时没有引入内存屏障,因此允许JITter进行优化,例如仅读取该值的缓存版本,或者甚至注意到该值不可能被写入,从而避免重复读取。

在这种非常特殊的情况下,您可以使用Volatile.Read(ref counter),它很可能会起作用,但您应该非常小心地尝试使用无锁或低锁编程,甚至使用这些低级别同步原语。您应该努力使用更高级别的同步原语。在这种特定情况下,Semaphore将是合适的。将它初始化为倒计时值的倒数,在回调中释放它,然后在方法中等待它。

对隐式参数(this)的锁定也是代码气味。您应该努力只锁定在非常小、严格控制的范围内的对象,以避免由于从广泛的代码库范围中取出对象的锁而导致死锁。