以原子方式锁定多个文件的最佳方法是什么?我想到的一种可能性是目录中的一个简单的.lock
文件(我只是受到我的程序的其他实例的保护;我不一定试图阻止其他程序不尊重锁。)然而,我所学到的关于线程安全的一切都是“糟糕的主意!”这是一种安全的方式吗?试图创建一个原子文件,所以如果我成功创建它,我知道我有锁吗?我应该怎么做呢?
我正在编写自己的错误跟踪器(主要是作为练习,我知道我可以在那里找到好的解决方案),它将错误存储在网络上的文件中。我设想它有点像SVN - 程序接管单个目录,并用于保存由跟踪器管理的错误,修订,屏幕截图等。我假设SVN有办法确保多个客户端不会在同一时间进行提交等。
答案 0 :(得分:1)
独占打开每个文件,如果找到无法打开的文件,则解锁已锁定的文件。始终按字母顺序锁定以避免死锁。
private List<FileStream> OpenExclusive(List<string> filenames)
{
var streams = new List<FileStream>(filenames.Count);
try
{
filenames.Sort();
foreach (var name in filenames)
{
streams.Add(File.Open(name,
FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None));
}
return streams;
}
catch (Exception)
{
CloseAll(streams);
return null;
}
}
private void CloseAll(List<FileStream> streams)
{
if (streams == null) return;
foreach (var stream in streams)
{
stream.Close();
}
}
答案 1 :(得分:0)
我推荐Mutex
,名为mutex的是操作系统范围。
答案 2 :(得分:0)
如果您打开一个独占访问的文件,它将保持锁定状态,任何其他尝试打开它的人都将失败。
答案 3 :(得分:0)
一个简单而可靠的选择是让应用程序在开始使用它们之前重命名包含这些文件的目录。它可以在启动之前将目录重命名为随机名称,并在完成后将其重命名。如果重命名成功,则不存在冲突的可能性。
一个缺点是,如果应用程序实例无法重命名该目录,则其他人将永远被锁定。您可能能够提出一些方案,其中重命名的目录名称对重命名的时间进行编码。如果其他实例看到超时时间已过,则可以控制它。
您是否已查看过现有的库,以便您不必提出自己的解决方案并处理所有边缘情况?不幸的是,我不知道有什么不妥。
答案 4 :(得分:0)
我希望多个用户从网络上的不同位置提交错误。
使用数据库引擎。
也许你是对的,但后来我很好奇SVN是如何运作的。在我看来,没有服务器,所有客户端只是访问SVN目录中的标准文件结构。