我确实理解.net锁确保只有一个线程执行在锁范围内找到的代码行 .
我不明白的是锁是否是原子的 . 执行锁定代码时是否可以中断线程?
例如 - 在我看来,如果一个锁不是原子的,那么下面的代码不是线程安全的:
Class example
{
private int myNumber;
private object context = new object();
void Write()
{
myNumber--;
}
void WriteLock()
{
lock (context)
{
myNumber++;
print(myNumber);
}
}
}
如果线程A执行方法WriteLock()并因为线程B正在执行Write()而中断,则myNumber可能会被不安全地更改 . 我对吗?
2 回答
不,那就像臭虫一样嘎嘎叫 . 那些运算符不是原子的,即使它们看起来像它 . 在引擎盖下,它们作为读 - 修改 - 写,三个操作而不是一个操作 . 所以他们自己不是原子的 . Write()中缺少的锁允许它与WriteLock()同时执行 . 结果是任意的,包括在WriteLock之前写入比赛时没有变化,并且当WriteLock在Write之前比赛时实际上减少了值 .
线程在拥有锁定时被中断并不重要,锁定将保持更长时间 .
使用Interlocked.Increment()和Decrement()来获得不需要锁定的更便宜的版本 .
检查msdn文档 . 我会想象它是原子的还是正在实现其他模式以确保不会发生这种情况 .
您的示例的问题是Write方法还应该在递减myNumber之前获取锁,以便其他任何线程都不能更改共享资源 .