Is there a global named reader/writer lock?

后端 未结 4 1082
执笔经年
执笔经年 2020-12-08 11:26

I have multiple asp.net web apps serving a set of files. Periodically, one will update the file before serving it, but it can\'t update the file if it is in use.

I c

4条回答
  •  孤城傲影
    2020-12-08 12:24

    I appreciate Jim Mischel's fine answer, but I see opportunity for performance improvement by avoiding Thread.Sleep() and avoiding lock contention when multiple readers try to acquire at the same time!

    Initialization

      Mutex writer = new Mutex(false, "Global\\MyWriterMutex");
      Semaphore readers = new Semaphore(int.MaxValue, int.MaxValue, "Global\\MyReadersSemaphore");
      EventWaitHandle readAllowed = new EventWaitHandle(true, EventResetMode.ManualReset, "Global\\MyReadAllowedEvent");
      EventWaitHandle readFinished = new EventWaitHandle(false, EventResetMode.ManualReset, "Global\\MyReadFinishedEvent");
    

    Reader

      while (true)
      {
        // signal that I'm reading 
        readers.WaitOne();
    
        // check whether I'm actually allowed to read
        if (readAllowed.WaitOne(0))
        {
          break; // great!
        }
    
        // oops, nevermind, signal that I'm not reading
        readers.Release();
        readFinished.Set();
    
        // block until it's ok to read
        readAllowed.WaitOne();
      }
    
      try
      {
        readData();
      }
      finally
      {
        // signal that I'm no longer reading
        readers.Release();
        readFinished.Set();
      }
    

    Writer

      // block until I am the only writer
      try
      {
        writer.WaitOne();
      }
      catch (AbandonedMutexException)
      {
        // The mutex was abandoned in another process, but it was still acquired
      }
    
      // signal that readers need to cease
      readAllowed.Reset();
    
      // loop until there are no readers
      int readerCount = -1;
      while (readerCount != 0)
      {
        // wipe the knowledge that a reader recently finished
        readFinished.Reset();
    
        // check if there is a reader
        readers.WaitOne();
        readerCount = int.MaxValue - (readers.Release() + 1);
        if (readerCount > 0)
        {
          // block until some reader finishes
          readFinished.WaitOne();
        }
      }
    
      try
      {
        writeData();
      }
      finally
      {
        // signal that readers may continue, and I am no longer the writer
        readAllowed.Set();
        writer.ReleaseMutex();
      }
    

提交回复
热议问题