我有一段代码片段,它使用回调来修改其他线程的计数器值。我正在使用锁定它并清空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--;
}
}
答案 0 :(得分:2)
每次访问线程之间共享的变量时,都需要锁定,而不仅仅是在一个位置。在这种情况下,while
循环中的代码在访问counter
时不会引入内存障碍,因此允许JITter进行优化,例如只读取值的缓存版本,甚至注意到该值无法写入,因此无法重复读取。
在这个非常具体的情况下你可以使用Volatile.Read(ref counter)
它可能会有效,但你应该非常警惕尝试使用无锁或低锁编程,甚至使用这些低级同步原语。您应该努力使用更高级别的同步原语。在这种特定情况下,Semaphore
是合适的。将其初始化为倒计时值的倒数,在回调中释放它,并在您的方法中等待它。
锁定隐式参数(this
)也是代码味道。您应该努力只锁定在一个非常小的,严格控制的范围内的对象,以避免由于从广泛的代码库中取出对象的锁而导致的死锁。