How do I achieve mutual exclusion like in the lock statement, but the block would be skipped if it is locked?
-
07-04-2021 - |
Question
Using the lock statement, one can "ensure that one thread does not enter a critical section of code while another thread is in the critical section. If another thread tries to enter a locked code, it will wait, block, until the object is released."
What if the behaviour I want is that if another thread tries to enter the locked code, it will just skip the whole code (instead of waiting the lock to be released)? An idea that come to my mind is using a flag, something like
if(flag) return;
flag = true;
//do stuff here
flag =false;
But I know this is not safe because two threads can pass the first line before anyone set to true, or the flag being never set to false in case of exceptions.. Can you suggest an improvement or an alternative?
Solution
Use this overload of Monitor.TryEnter
, which lets you specify a timeout.
Attempts, for the specified amount of time, to acquire an exclusive lock on the specified object.
Return Value Type: System.Boolean true if the current thread acquires the lock without blocking; otherwise, false.
In your case, you probably want to use a timeout of close to TimeSpan.Zero
.
If you don't want the thread attempting to take the lock to wait for any length of time, you can just this overload of Monitor.TryEnter
, which does not accept a TimeSpan
argument. This method will immediately return without waiting - very close to the sentiment of the flag technique you are trying to use.
OTHER TIPS
You need Semaphores with a limit 1 and timeout period 0 miliseconds
By using Semaphore you can say that only a limited number of threads can access a piece of code at a time.
See this sample for how to use it
You need to use this method for waiting
bool WaitOne(int millisecondsTimeout)
specify timeout period = 0; in this way your waiting threads will wait 0 second which means they will simply skip the code
class SemaphoreExample
{
// Three reserved slots for threads
public static Semaphore Pool = new Semaphore(1, 0);
public static void Main(string[] args)
{
// Create and start 20 threads
for (int i = 0; i < 20; i++)
{
Thread t = new Thread(new ThreadStart(DoWork));
t.Start();
}
Console.ReadLine();
}
private static void DoWork()
{
// Wait 0 miliseconds
SemaphoreExample.Pool.WaitOne(0);
#region Area Protected By Semaphore
Console.WriteLine("Acquired slot...");
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i + 1);
}
Console.WriteLine("Released slot...");
#endregion
// Release the semaphore slot
SemaphoreExample.Pool.Release();
}
}
you can use Monitor.TryEnter