I have written a sample console application which creates a mutex as shown in below code sample. I am launching this application directly from Visual Studio (VS2013) by pressing Ctrl + F5 (running the application without debugger). For the 1st instance of console application I acquire the mutex and the following line is displayed in console:
New Instance created...
However, when I create a second instance of console application using Ctrl + F5 again, I get the following message in the console:
Instance already acquired...
even though I explicitly release mutex after 500ms with this line of code:
mut.ReleaseMutex();
In the same thread which acquires the mutex, I still see that my second instance of console application waits for the mutex to be released.
Can someone explain to me why is it so or correct me if I am doing something wrong? If I understand, ReleaseMutex
should release the mutex from the same thread which acquires it via mut.WaitOne(0)
call so that any other thread waiting to acquire mutex should be provided ownership. However, in this case I am not able to see it working.
If I close the 1st instance which acquired mutex (still my second is alive) and try to launch a 3rd instance with Ctrl+F5, I can see that there is an AbandonedMutexException
:
Unhandled Exception: System.Threading.AbandonedMutexException: The wait completed due to an abandoned mutex.
PS: Interestingly I can see that this works fine if I pass false
in mutex constructor as
static Mutex mut = new Mutex(false, "Global\\test");
What's the significance of initiallyOwned
parameter in the
public Mutex(bool initiallyOwned, string name);
constructor version of mutex class?
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;
}
}
}
In the real sense it has no meaning or full form. It was developed by Dennis Ritchie and Ken Thompson at AT&T bell Lab. First, they used to call it as B language then later they made some improvement into it and renamed it as C and its superscript as C++ which was invented by Dr.
C is a structured, procedural programming language that has been widely used both for operating systems and applications and that has had a wide following in the academic community. Many versions of UNIX-based operating systems are written in C.
C is a general-purpose language that most programmers learn before moving on to more complex languages. From Unix and Windows to Tic Tac Toe and Photoshop, several of the most commonly used applications today have been built on C. It is easy to learn because: A simple syntax with only 32 keywords.
C programming language is a machine-independent programming language that is mainly used to create many types of applications and operating systems such as Windows, and other complicated programs such as the Oracle database, Git, Python interpreter, and games and is considered a programming foundation in the process of ...
So to understand a problem you need to know about two things:
initiallyOwned
parameter worksIf you create Mutex
with initiallyOwned
= true - it will try to immediately acquire ownership BUT only if such mutex is not already created. So the first instance of your application immediatly acquires ownership of the mutex. It's about the same as doing:
var mut = new Mutex(false, "Global\\test");
mut.WaitOne();
If this mutex already exists, it will not try to acquire ownership. To see if mutex was created (and so, it you already own it), you can use this overload:
bool createdNew;
mut = new Mutex(true, "Global\\test", out createdNew);
Now, Mutex
allows several calls to WaitOne
and ReleaseMutex
, from the same thread. If you called WaitOne
multiple times - you need to call ReleaseMutex
the same amount of times to release it. However, for your first instance, you call WaitOne
twice: first because of initiallyOwned
parameter (and because mutex does not exists yet and is created), and second time you call it explicitly. But you only call ReleaseMutex
once, and as such your mutex is not released and is owned by first instance. When you close this instance - mutex is still not released and so becomes abandoned.
Here is a code example illustrating those points:
static Mutex mut;
static void Main(string[] args)
{
bool createdNew;
mut = new Mutex(true, "Global\\test", out createdNew);
if (createdNew) {
Console.WriteLine("New instance created with initially owned = true");
}
else if (IsInstance())
{
Console.WriteLine("New Instance created...");
}
else
{
Console.WriteLine("Instance already acquired...");
}
if (createdNew)
{
Thread.Sleep(500);
mut.ReleaseMutex();
}
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With