【发布时间】:2017-02-16 13:30:58
【问题描述】:
我编写了一个示例控制台应用程序,它创建了一个互斥锁,如下面的代码示例所示。我通过按 Ctrl + F5 (在没有调试器的情况下运行应用程序)直接从 Visual Studio (VS2013) 启动此应用程序。对于控制台应用程序的第一个实例,我获取了互斥锁,并且控制台中显示了以下行:
已创建新实例...
但是,当我再次使用 Ctrl + F5 创建控制台应用程序的第二个实例时,我在控制台中收到以下消息:
实例已经获得...
即使我使用这行代码在 500 毫秒后显式释放互斥锁:
mut.ReleaseMutex();
在获取互斥锁的同一个线程中,我仍然看到我的第二个控制台应用程序实例等待互斥锁被释放。
如果我做错了什么,有人可以向我解释为什么会这样或纠正我吗?如果我理解,ReleaseMutex 应该从通过mut.WaitOne(0) 调用获取互斥锁的同一线程释放互斥锁,以便为任何其他等待获取互斥锁的线程提供所有权。但是,在这种情况下,我无法看到它工作。
如果我关闭获得互斥锁的第一个实例(我的第二个仍然存在)并尝试使用 Ctrl+F5 启动第三个实例,我可以看到有一个 AbandonedMutexException:
未处理的异常:System.Threading.AbandonedMutexException:由于被放弃的互斥体,等待已完成。
PS:有趣的是,如果我在 mutex 构造函数中将 false 传递为
static Mutex mut = new Mutex(false, "Global\\test");
initiallyOwned参数中的意义是什么
public Mutex(bool initiallyOwned, string name);
互斥类的构造函数版本?
Console output for 2 instances run from VS
class Program
{
static Mutex mut = new Mutex(true, "Global\\test");
static void Main(string[] args)
{
if (IsInstance())
{
Console.WriteLine("New Instance created...");
}
else
{
Console.WriteLine("Instance already acquired...");
}
Console.ReadLine();
}
static bool IsInstance()
{
if (!mut.WaitOne(0))
{
Console.WriteLine("Thread id {0} Waiting at Mutex...",AppDomain.GetCurrentThreadId());
return false;
}
else
{
Console.WriteLine("Thread id {0} got Mutex...", AppDomain.GetCurrentThreadId());
Thread.Sleep(500);
mut.ReleaseMutex();
return true;
}
}
}
【问题讨论】:
-
如果将
true作为initiallyOwned传递,当前线程将在创建后立即尝试获取互斥锁。 -
@Leandro Taset 是的,我明白这一点,但为什么同一线程上的调用
mut.ReleaseMutex();没有释放互斥锁?这就是我想要理解的。有趣的是看到false可以正常工作,为什么不使用true。如果它打算这样工作,在哪些情况下应该使用true,以及在哪些情况下使用false。 -
正如@LeandroTaset 所说,这种模式被破坏了,因为它导致了废弃的互斥锁。请参阅this 答案。
-
“它本来就是这样工作的” - 不,如果你运行你的第一个副本,它将占用互斥锁(由于构造函数参数),但会失败
WaitOne检查 = 不释放 = 放弃互斥锁。WaitOne不是“检查此线程是否拥有所有权”,而是“尝试获取所有权”,因此它将返回false(因为 something 已经拥有互斥锁)。阅读有关abandoned mutex 的更多信息。 -
@Evk,感谢您的解释。我现在已经澄清了我的疑问..
标签: c# multithreading mutex