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--;
}
}
每次访问线程之间共享的变量时,都需要锁,而不仅仅是在一个位置。在这种情况下,while
循环中的代码在访问counter
时没有引入内存屏障,因此允许JITter进行优化,例如仅读取该值的缓存版本,或者甚至注意到该值不可能被写入,从而避免重复读取。
在这种非常特殊的情况下,您可以使用Volatile.Read(ref counter)
,它很可能会起作用,但您应该非常小心地尝试使用无锁或低锁编程,甚至使用这些低级别同步原语。您应该努力使用更高级别的同步原语。在这种特定情况下,Semaphore
将是合适的。将它初始化为倒计时值的倒数,在回调中释放它,然后在方法中等待它。
对隐式参数(this
)的锁定也是代码气味。您应该努力只锁定在非常小、严格控制的范围内的对象,以避免由于从广泛的代码库范围中取出对象的锁而导致死锁。