这种互斥模式是否像我认为的那样安全?如果是这样,你怎么称呼它?
lock (_lock) {
if (_flag) return;
else _flag = true;
}
try {
//critical code...
}
finally {
_flag = false;
}
我想确保关键部分,但没有其他线程堆积等待获取锁。显然,我确保标志没有设置在其他任何地方。有没有更好的办法?
这种互斥模式是否像我认为的那样安全?如果是这样,你怎么称呼它?
lock (_lock) {
if (_flag) return;
else _flag = true;
}
try {
//critical code...
}
finally {
_flag = false;
}
我想确保关键部分,但没有其他线程堆积等待获取锁。显然,我确保标志没有设置在其他任何地方。有没有更好的办法?
不,那不安全。如果要确保互斥而不阻塞,可以使用 Monitor.TryEnter:
if (Monitor.TryEnter(lockObj, 0)) {
// got the lock !
try {
// code
}
finally { // release the lock
Monitor.Exit(lockObj);
}
}
你看过Monitor.TryEnter
吗?
互斥模式的正确性取决于赋值 _flag=false 是原子的。想象一下如果分配可能被另一个线程中断会发生什么。如果分配的中间结果可能被测试解释为错误,则一个分配可能导致多个线程进入临界区。
互斥模式的正确性还取决于编译器中是否缺少可能重新排列语句顺序的优化。想象一个“智能”编译器,它会将赋值 _flag=false 向上移动,因为 _flag 在中间的代码中没有被引用(并且中间的代码不会抛出异常)。然后编译器可以优化锁定部分中的部分以读取
if(_flag) return;
这两个模式为什么会失败的例子都是高度推测性的,我认为你可以安全地假设它有效。但是,如果存在另一个可以根据需要工作的选项,您最好使用它(请参阅其他帖子)。如果同一代码中有其他开发人员,则无需考虑该模式是否有效。
lock(Object)
一个简单的陈述不会起作用吗?在幕后,它在块Monitor
内创建和关键部分try... finally
。
private static readonly Object lockMe = new Object();
lock(lockMe)
{
// critical code
}