今天早些时候我正在调试有点像这样的东西:
class Foo {
void AccessCriticalSection() {
try {
if (IO.File.Exists("\\path\to\lock.txt")
throw new Exception();
System.IO.File.Create("\\path\to\lock.txt");
criticalSection();
} catch (Exception ex) {
// ignored
}
}
void CriticalSection() {
// banana banana banana
System.IO.File.Delete("\\path\to\lock.txt");
}
}
让我们甚至不知道这是多么可怕......但它本质上是试图使用一个名为lock.txt
的文件作为其互斥体。该操作不是原子操作,如果另一个进程正在使用它,其他进程只是没有通过关键部分(如果您可以相信它们,它们的目的是能够在锁定释放后继续)等等。显然它需要修复。
如何正确获取锁以跨多个进程同步对文件系统的访问?这些进程是同一进程的多个实例,因此它们可以共享一些协议而不是专门锁定目录(即,它们可以轻松地使用与private final static Object lock = new Object();
之类的某些类锁定的所有实例等效的同步访问静态方法)
答案 0 :(得分:8)
您应该使用Mutex。
同步原语,也可用于进程间同步。
互斥锁是本地到进程或名为。要支持进程间同步,您需要使用名为mutex的 。
命名系统互斥锁在整个操作系统中都是可见的,可用于同步进程的活动。
这是一个使用共享互斥锁演示进程间同步的示例程序。
class Program
{
static void Main(string[] args)
{
const string SHARED_MUTEX_NAME = "something";
int pid = Process.GetCurrentProcess().Id;
using (Mutex mtx = new Mutex(false, SHARED_MUTEX_NAME))
{
while (true)
{
Console.WriteLine("Press any key to let process {0} acquire the shared mutex.", pid);
Console.ReadKey();
while (!mtx.WaitOne(1000))
{
Console.WriteLine("Process {0} is waiting for the shared mutex...", pid);
}
Console.WriteLine("Process {0} has acquired the shared mutex. Press any key to release it.", pid);
Console.ReadKey();
mtx.ReleaseMutex();
Console.WriteLine("Process {0} released the shared mutex.", pid);
}
}
}
}
示例程序输出:
紫色线条表示在两个进程之间传输共享互斥锁控制的点。
要同步对单个文件的访问,您应该使用基于受保护文件的规范化路径的互斥锁名称。
Here's how you can create a normalized path:
public static string NormalizePath(string path)
{
return Path.GetFullPath(new Uri(path).LocalPath)
.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar)
.ToUpperInvariant();
}