这个文件锁定机制会起作用还是会成为竞争条件?

时间:2012-06-05 14:00:40

标签: file console locking

我有一个运行不同命令的控制台程序。我希望能够并行运行程序的多个实例,但是,我希望防止并行处理特定命令。

我想到了一个简单的文件锁定系统。

鉴于命令“foo”不允许并行运行,那会起作用吗?

  1. 在运行foo之前检查文件.lock_foo_ *是否存在(如果是,中止)
  2. 如果没有,请创建文件.lock_foo_GUID
  3. 检查.lock_foo_GUID是否存在以及是否存在其他.lock_foo_ *文件
  4. 如果有另一个.lock_foo_ *文件,这意味着另一个实例在同时创建了一个,我们中止并删除了我们的锁文件。

    我想知道是否有任何竞争条件,以及这是否是处理它的正确方法?

    更新

    我认为它实际上比最初预期的更容易(至少在Windows上)。我认为这个答案让我走上正轨。

    我认为这样的事情应该有效

    public bool CreateLock(string fileName){
         try{
             File.Open(string.Format(".lock_{0}",fileName), FileMode.Create, FileAccess.ReadWrite, FileShare.None);
          }
          catch (Exception exception){
               return false;
          }
          return true;
    }
    

    操作系统将确保仅在文件尚不存在时才创建该文件,否则将引发异常。所以这种方法应该是安全的。不幸的是,这在UNIX上不起作用。

1 个答案:

答案 0 :(得分:0)

你的逻辑看起来很不错。但是,如果您感兴趣,那么已经有多个命令行实用程序可以执行您想要的操作,例如lockfileflock

试试man 1 lockfile。我怀疑该联机帮助页将简洁地回答您的问题。

另一方面,如果你需要或者更喜欢自己实现这个,那么你建议的方法几乎是正确的,但必须零星地,偶尔失败。这令人沮丧,但这是你想要做的事情固有的。原因是短暂的间隔介于(1)检查另一个进程是否已锁定资源和(2)锁定资源之间。如果在这个短暂的时间间隔内另一个进程应该锁定资源会发生什么?

所需要的是原子操作,它以某种方式检查并锁定为单个不间断的步骤。幸运的是,现代CPU提供了这样的原子操作,现代操作系统内核会对它们进行曝光,因此您可以确实可靠地执行您想要的操作。

如果您对此感兴趣,那么您可以查阅Microsoft LockFileLockFileEx的开发文档。