我确实知道.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可能会被不安全地更改。我是对的吗?
答案 0 :(得分:2)
不,这就像一个小虫一样大声嘎嘎叫。那些运算符不是原子的,即使它们看起来像它。在引擎盖下,它们作为读 - 修改 - 写,三个操作而不是一个操作。所以他们自己不是原子的。 Write()中缺少的锁允许它与WriteLock()同时执行。结果是任意的,包括在WriteLock之前写入比赛时没有变化,并且当WriteLock在Write之前比赛时实际上减少了值。
线程在拥有锁定时被中断并不重要,锁定只会持续更长时间。
使用Interlocked.Increment()和Decrement()来获得不需要 lock 的更便宜的版本。
答案 1 :(得分:1)
检查msdn文档。我会想象它是原子的还是正在实现其他模式以确保不会发生这种情况。
您的示例的问题是Write方法还应该在递减myNumber之前获取锁,以便其他线程不会改变共享资源。
void Write()
{
lock(context) {
myNumber--;
}
}