当在锁部分中设置的volatile变量的新值可用于其他线程吗?

时间:2018-06-19 11:29:37

标签: c# multithreading

我有一个方法Test,它可以从许多线程中执行,并且我不想在方法已经执行时锁定要执行它们的所有线程。我的想法是在执行活动时创建易失性isProcessing并将其设置为true

但是我不知道C#内存模型,也无法理解其他线程何时会看到isProcessing的新值。它会在设置isProcessing值后立即执行还是仅在退出lock部分后立即执行?

代码示例:

private volatile bool isProcessing = false;

private void Test()
{
  if (isProcessing) return;   
  lock(this){
    try{   
      isProcessing = true;
      //do something
    }
    finally{ 
      isProcessing = false;  
    }
  }
}

1 个答案:

答案 0 :(得分:1)

这是使用两个单独的锁执行此操作的方法。请注意,锁定可能对其他呼叫站点可见的对象不是一种好习惯。

    private bool isProcessing = false;
    private object readLock = new object();
    private object processingLock = new object();
    private void Test()
    {
        Monitor.Enter(readLock);
        if (isProcessing)
        {
            Monitor.Exit(readLock);
            return;
        }
        lock (processingLock)
        {
            isProcessing = true;
            Monitor.Exit(readLock);
            try
            {
                //do something
            }
            finally
            {
                isProcessing = false;
            }
        }
    }

一个更简单的解决方案是使用Mutex,而不是使用Monitors。

    Mutex processingMutex = new Mutex(false);
    private void Test2()
    {
        if (!processingMutex.WaitOne(0))
        {
            return;
        }
        try
        {
            //do processing
        }
        finally
        {
            processingMutex.ReleaseMutex();
        }
    }

Mutex还可以通过将WaitOne的参数设置为非零值来使您短暂等待其他线程是否结束。