原始并发读写的线程安全性

Cel*_*Cel 5 .net c# concurrency multithreading thread-safety

  • 下面简化说明,.NET如何处理这种情况?
  • 如果它会导致问题,我是否必须锁定/门控访问可能有时被写入+从不同线程访问的每个字段/属性?

某个地方

public class CrossRoads(){
    public int _timeouts;
}
Run Code Online (Sandbox Code Playgroud)

后台线程编写者

public void TimeIsUp(CrossRoads crossRoads){
    crossRoads._timeouts++;
}
Run Code Online (Sandbox Code Playgroud)

可能在同一时间,试图在其他地方阅读

public void HowManyTimeOuts(CrossRoads crossRoads){
    int timeOuts = crossRoads._timeouts;
}
Run Code Online (Sandbox Code Playgroud)

com*_*ech 12

简单的答案是,如果从多个线程同时访问上述代码,则能够导致问题.

.Net框架提供了两种解决方案:互锁和线程同步.

对于简单的数据类型操作(即整数),使用Interlocked类互锁将正常工作,是推荐的方法.

实际上,interlocked提供了特定的方法(Increment和Decrement),使这个过程变得简单:

将IncrementCount方法添加到CrossRoads类:

public void IncrementCount() {
    Interlocked.Increment(ref _timeouts);
}
Run Code Online (Sandbox Code Playgroud)

然后从你的后台工作者那里调用它:

public void TimeIsUp(CrossRoads crossRoads){
    crossRoads.IncrementCount();
}
Run Code Online (Sandbox Code Playgroud)

除非32位操作系统上的64位值,否则读取值是原子的.有关更多详细信息,请参阅Interlocked.Read方法文档.

对于类对象或更复杂的操作,您将需要使用线程同步锁定(在VB.Net中锁定C#或SyncLock).

这是通过在要应用锁定的级别(例如,在类中)创建静态同步对象,获取对该对象的锁定以及在该锁定内执行(仅)必要的操作来实现的:

    private static object SynchronizationObject = new Object();

    public void PerformSomeCriticalWork()
    {
        lock (SynchronizationObject)
        {
            // do some critical work
        }
    }
Run Code Online (Sandbox Code Playgroud)