Finally here is the edit:
I am synchronizing two different processes with a semaphore:
var semaphore = new Semaphore(0, 1, "semName");
so I have process A and process B they happen to be different executables.
Process A
static void Main(string[] args)
{
Console.Write("Process A");
Task.Factory.StartNew(() =>
{
var semaphoreName = "sem";
var semaphore = Semaphore.OpenExisting(semaphoreName);
Thread.Sleep(100);
semaphore.Release();
semaphore.WaitOne();
semaphore.Release();
Console.Write("Process A Completed!");
});
Console.Read();
}
Process B (Different console app)
static void Main(string[] args)
{
Console.Write("Process B");
Task.Factory.StartNew(() =>
{
var semaphoreName = "sem";
var semaphore = new Semaphore(0, 1, semaphoreName);
semaphore.WaitOne();
Thread.Sleep(1000);
semaphore.Release();
semaphore.WaitOne();
Console.Write("Process B Completed!");
});
Console.Read();
}
If I debug the processes or place a Thread.Sleep I am able to reach the last line Console.Write("Process A Completed!"); How can I solve this problem without having to place Thread.Sleep(100);?
Edit
There is no race condition!! Maybe I am wrong correct me if I am. Anyways here is the reason why I think there is no race condition:
Process A
static void Main(string[] args)
{
Console.Write("Process A");
var semaphoreName = "sem";
Task.Factory.StartNew(() =>
{
var semaphore = Semaphore.OpenExisting(semaphoreName);
semaphore.Release();
semaphore.WaitOne();
// this line should never be reached but it is!!!
Console.Write("Process A Completed!");
});
Console.Read();
}
Processes B
static void Main(string[] args)
{
Console.Write("Process B");
var semaphoreName = "sem";
Task.Factory.StartNew(() =>
{
var semaphore = new Semaphore(0, 1, semaphoreName);
semaphore.WaitOne();
// important to have these lines
int a = 0;
for (var i = 0; i < 1000000000; i++)
a = i;
Thread.Sleep(10000); // there should not be a race condition any more!!!!
Console.Write("Process B Completed!");
});
Console.Read();
}
note that on process A we should never reach the line: Console.Write("Process A Completed!"); But we do…
Process B sleeps for 10000 seconds so there is no reason why there should be a race condition. Moreover if I remove the loop for (var i = 0; i < 1000000000; i++) I don’t get that behavior.
I haven’t been able to find any documentation that states that threads waiting on a semaphore will necessarily be released in the same order that they begin waiting on it. Is it not therefore possible that the
sem.WaitOne()in process B is being released by thesem.Release()immediately above it, without giving process A a chance to enter?The addition of the
Thread.Sleep()prior to waiting on the semaphore in process B presumably gives process A a chance to enter the semaphore instead.You’ve not made it entirely clear why you’re using a semaphore in this way, or what the
sem.WaitOne()in process B is waiting for (since process A never releases the semaphore in your example code), so it’s difficult to suggest an improvement that fix the problem.If however you’re intending to have process A wait for process B to start before beginning its work, then for process B to wait for process A to complete the work before continuing, it seems that two
ManualResetEvents could achieve this more effectively (specifically a “Process B ready” event waited on by process A, and a “Process A finished” event waited on by process B).Possible solution:
Process A:
Process B: