【问题标题】:Using a named mutex to lock a file使用命名互斥锁锁定文件
【发布时间】:2012-01-31 10:01:46
【问题描述】:

我正在使用命名互斥锁来锁定对文件(路径为“strFilePath”)的访问,如下所示:

private void DoSomethingsWithAFile(string strFilePath)
{
      Mutex mutex = new Mutex(false,strFilePath.Replace("\\",""));
      try
      {
         mutex.WaitOne();
         //do something with the file....
      }
      catch(Exception ex)
      {
         //handle exception
      }
      finally
      {
         mutex.ReleaseMutex();
      }
 }

因此,这样代码只会在已经处理同一个文件时阻塞线程。 好吧,我对此进行了测试,似乎可以正常工作,但我真的很想知道您对此的看法。

【问题讨论】:

  • 您是否正在尝试实现经典的生产者-消费者-场景?向我们提供有关您的方案的更多信息 - 很难对您的实际问题进行修剪/帮助!
  • 任何其他软件,如 Windows 资源管理器、记事本等,对您的“基于互斥锁”一无所知,并且很乐意忽略它!
  • @Yahia 是的,我知道,但这不是想法。我使用这个构造在我的程序中进行线程同步。如果我不希望其他程序访问该文件,我将使用普通的文件锁定机制。
  • @Andreas 好吧,我的代码中有不同的线程可以将数据写入/删除文件,我像这样同步文件。
  • @Jurgen 您需要提供更多信息然后...您只需要一种机制来“锁定”多线程进程中的磁贴吗?您使用的是什么 .NET 版本?

标签: c# .net producer-consumer


【解决方案1】:

由于您正在谈论具有多个线程的生产者-消费者情况,“标准解决方案是使用 BlockingCollection,它是 .NET 4 及更高版本的一部分 - 多个信息链接:

如果您只是想让锁定过程正常工作,那么:

ConcurrentDictionaryTryAdd 方法调用结合使用...如果它返回true,则文件未“锁定”,现在已“锁定”,因此线程可以继续 - 并“解锁”最后通过调用Remove...任何其他线程同时获得false,并可以决定要做什么...

我肯定会推荐 BlockingCollection 方法!

【讨论】:

  • dah ... 赌我 4 秒 ... :)
【解决方案2】:

我遇到了许多可以写入同一个文件的线程的相同问题。

互斥量不好的原因之一是因为它慢:

duration of call mutexSyncTest: 00:00:08.9795826    
duration of call NamedLockTest: 00:00:00.2565797

BlockingCollection 集合 - 非常好的主意,但对于我这种很少发生冲突的情况,并行写入比串行写入更好。使用字典的方式也更容易实现。

我使用这个解决方案(已更新):

public class NamedLock
{
    private class LockAndRefCounter
    {
        public long refCount;
    }

    private ConcurrentDictionary<string, LockAndRefCounter> locksDictionary = new ConcurrentDictionary<string, LockAndRefCounter>();

    public void DoWithLockBy(string key, Action actionWithLock)
    {
        var lockObject = new LockAndRefCounter();

        var keyLock = locksDictionary.GetOrAdd(key, lockObject);
        Interlocked.Increment(ref keyLock.refCount);

        lock (keyLock)
        {
            actionWithLock();

            Interlocked.Decrement(ref keyLock.refCount);
            if (Interlocked.Read(ref keyLock.refCount) <= 0)
            {
                LockAndRefCounter removed;
                locksDictionary.TryRemove(key, out removed);
            }
        }
    }
}

【讨论】:

  • 我认为从字典中删除条目存在问题。如果三个客户端调用该方法会怎样:第一个创建密钥并获取锁,第二个获取现有密钥并等待锁定,第一个完成并移除密钥并释放锁,第二个可以启动,第三个来并在第二个完成之前创建一个新密钥并获取一个新锁。第二和第三现在同时运行。
【解决方案3】:

另一种选择是:创建一个在队列上工作的消费者线程,如果它为空则阻塞。您可以让多个生产者线程将多个文件路径添加到此队列并通知消费者。

从 .net 4.0 开始,有一个不错的新类:System.Collections.Concurrent.BlockingCollection&lt;T&gt;

不久前我也有同样的issue here on Stack Overflow - How do I implement my own advanced Producer/Consumer scenario?

【讨论】:

    猜你喜欢
    • 2017-09-24
    • 2015-04-14
    • 1970-01-01
    • 1970-01-01
    • 2018-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多