0

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

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

给定命令“foo”不允许并行运行,这行得通吗?

  1. 在运行 foo 之前检查文件 .lock_foo_* 是否存在(如果存在,则中止)
  2. 如果没有,创建文件 .lock_foo_GUID
  3. 检查 .lock_foo_GUID 是否存在以及是否不存在其他 .lock_foo_* 文件

如果有另一个 .lock_foo_* 文件,这意味着另一个实例同时创建了一个,我们中止并删除我们的锁定文件。

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

更新

我认为它实际上比最初预期的要容易(至少在 Windows 上)。我认为 thb 的回答让我走上了正确的道路。

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

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 上不起作用。

4

1 回答 1

0

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

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

另一方面,如果您需要或更喜欢自己实现此功能,那么您建议的方法几乎是正确的,但必须偶尔地、非常偶尔地失败。这令人沮丧,但这是您尝试做的事情所固有的。原因是在 (1) 检查另一个进程是否锁定了资源和 (2) 锁定资源之间插入了一个短暂的时间间隔。如果在这个短暂的时间间隔内,另一个进程应该锁定资源,会发生什么?

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

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

于 2012-06-05T14:05:29.880 回答