文件锁定的变化

Variations on file locking

我在 , to ask about "concurrent" writes to an XML file, and it got flagged as a duplicate and referenced 上启动了一个线程,该线程讨论在与写入文件相同的文件夹中创建一个锁定文件,作为处理这种情况的一种方法。 这对我来说似乎不优雅,用隐藏文件写入网络,特别是当我们有能力锁定文件时,只是没有能力(似乎)锁定文件然后,你知道,用它做点什么. 所以,我的想法是采取不同的方法。 1:用 $file = [IO.File]::Open($path, 'Open', 'ReadWrite', 'None') 锁定文件 我已经确认我不能锁定它两次,所以我的代码的一个实例在任何时候只能有一个锁。 2:将项目复制到本地临时文件夹。 3:阅读该副本并根据需要附加数据。 4:保存回临时文件。 5:使用$file.Close()解除锁定 6:立即将临时文件复制到原始文件上。 风险似乎在 5 和 6 之间。另一个实例可以在第一个实例删除锁之后但在它用修改后的临时文件覆盖文件之前设置锁。

这是否是采用单独锁定文件方法的原因?因为 "lock" 会保留在原位直到修改被保存?

对于我认为 .NET 或 Powershell 应该处理的事情来说,这一切似乎都是令人讨厌的事情。

一种经常使用的做法 - 通过所有应用程序的相互合作 - 是 "sentinel file" 或 "lock file." 有时仅仅存在文件就足够了;有时 变成 "the file that you lock."

所有应用程序都必须了解您的约定并且必须遵守它。这将允许您在不受其他合作应用程序干扰的情况下操作XML文件。

很好地总结了最佳实践。

关于你的问题:

The risk seems to be between 5 & 6. Another instance could set a lock after the first instance removes the lock, but before it overwrites the file with the revised temp file.

Is that risk the reason for the separate lock file approach? Because then the "lock" stays in place until after the revisions are saved?

是的,协作进程遵守的单独锁定文件将防止此类竞争条件

但是,可以解决这个问题没有锁定文件,尽管以执行更新所需的时间为代价:

  • 锁定文件允许您“声明”该文件而无需独占锁定它,因此您可以准备更新,而其他进程仍然可以读取文件。然后,您可以将独占锁定限制为使用先前准备的内容重写/替换文件的行为。

    • 换句话说:按照惯例,锁文件保证更新操作的原子性,但通过将独占锁定限制为仅重写/替换行为来最小化其持续时间(不包括花在阅读和更新准备上的时间)。
  • 或者,您可以通过打开带有排他锁的文件来保证原子性,在您读取、修改和保存之前不会释放该文件.

    • 换句话说:实现变得更简单(无锁文件),但更新时间更长

      • 你的其他问题演示了该技术。
    • 不过,即便如此,也需要其他进程的配合:也就是说,读者和作者都需要准备如果在正在进行的更新操作期间打开文件进行读取失败(暂时),则在循环中重试