锁定机制,提供有关.NET 3.5中的状态的信息

时间:2010-06-24 09:52:24

标签: c# locking interlocked

我正在尝试找到一种方法来提供对资源的独占访问,同时提供有关锁定状态的信息(_isWorking)以供其他类读取。

这是我到目前为止所提出的:

    private int _isWorking = 0;

    public bool IsWorking
    {
        get { return Interlocked.CompareExchange(ref _isWorking, 0, 0) == 1; }
    }

    public void LaunchProcess()
    {
        if (Interlocked.CompareExchange(ref _isWorking, 1, 0) == 0)
        {
            try
            {
                DoExpansiveProcess();
            }
            finally
            {
                Interlocked.Exchange(ref _isWorking, 0);
            }
        }
    }

    public void DoExpansiveProcess()
    {
        Thread.Sleep(30000);
    }

它不能完全像锁一样工作,因为第二个线程在看到一个线程已经在运行该进程时,只会离开该方法而不执行任何操作。

这样做是否正确?或者是否有更适合此目的的C#3.5结构?

如何实现一个“真正的”锁定场景,第二个线程在第一个线程结束后仍会执行该方法,同时提供有关状态的信息?

3 个答案:

答案 0 :(得分:1)

假设我正确理解了你的问题,那么我认为你所追求的是Monitor.TryEnter方法,其超时值为0.它会尝试获取锁定,但是如果超时为0,它将始终返回立即获得指示锁是否实际获得的值。这里的含义是,如果没有获得锁定,则认为它已被其他人获取。问题是,如果返回true,那么您必须立即通过调用Monitor.Exit来释放它。

也许这是一个更好的解决方案:

public class Worker
{
  private Object m_LockObject = new Object();
  private volatile bool m_IsWorking = false;

  public bool IsWorking
  {
    get { return m_IsWorking; }
  }

  public void LaunchProcess()
  {
    lock (m_LockObject)
    {
      m_IsWorking = true;
      DoExpansiveProcess();
      m_IsWorking = false;
    }
  }
}

答案 1 :(得分:0)

System.Threading.ManualResetEvent可能会在这里提供帮助。只需对它做一个WaitOne()。如果它被使用,那么它将返回为假。如果它没有使用它可用。

其中一个WaitOne()重载需要花费一些时间才能等待。如果你使用WaitOne(0),则等待将立即以非阻塞方式返回。

您应该对.Net提供的同步原语进行一些研究:

System.Threading.Monitor lock() { }
System.Threading.ManualResetEvent
System.Threading.AutoResetEvent
System.Threading.Semaphore
System.Threading.Mutex

答案 2 :(得分:0)

我认为你的方法通常应该是正确的,并且肯定比使用ManualResetEvent(如果它完全相关)要快得多 - 因为ManualResetEvent包装了底层的非托管原语。

为了使这种方法安全,_isWorking必须是私有的。