使用线程时是否需要锁定“只读”服务?

时间:2008-12-19 22:01:08

标签: c# multithreading

我有一个服务,我正在重写使用线程。我知道来自一个线程的状态不应被另一个线程访问,但我对“状态”的构成有点困惑。这是否意味着方法范围之外的任何字段/属性/方法?

具体来说,我的服务看起来像这样:

public class MyService
{
      private IRepository<MyClass> repository;
      private ILogger log;
      ...
      public void MyMethod()
      {
        ...
        var t = new Thread(MyMethodAsync);
        t.Start(someState);
      }

      //Is this OK???
      public void MyMethodAsync(object state)
      {
          var someState = (MyState)state;
          log.Log("Starting");
          var someData = repository.GetSomeData(someState.Property);
          //process data
          log.Log("Done");            
      }

      //Or should I be doing this:
      public void MyMethodAsync2(object state)
      {
          var someState = (MyState)state;
          lock(log){
             log.Log("Starting");  }

          lock(repository){         
             var someData = repository.GetSomeData(someState.Property);}

          //process data   
          lock(log){
             log.Log("Done"); }            
      }
}

3 个答案:

答案 0 :(得分:2)

“State”是类中包含的所有数据,并发性的真正问题是写访问,所以你的直觉是正确的。

答案 1 :(得分:1)

呃......不,你不需要锁定只读资源。锁定它们的目的是,如果您需要在写入之前检查资源的值,那么另一个资源不能更改读取和写入之间的值。即:

SyncLock MyQueue
  If MyQueue.Length = 0 Then
    PauseFlag.Reset
  End If
End SyncLock

如果我们在设置标志以暂停我们的进程队列线程然后另一个资源将一个项目添加到队列之前检查队列的长度,那么我们的进程队列线程将处于暂停状态,而可能在检查队列长度和设置暂停标志之间添加了项目......

如果所有资源只以只读方式访问队列(不是我能想到一个只读队列的单个有用应用程序),那么就不需要锁定它。

答案 2 :(得分:0)

更糟糕的是,锁定只读结构是创建死锁的好方法。