I have 5 threads which try to enter a critical section of a static class at a random time. If another thread is in the critical section i want the others to 'back-off' and try at a later time. The problem is that it seems that the lock is not being released after the first thread enters the critical section because for the others false will always be returned if i 'breakpoint' at Monitor.TryEnter(thisLock).
Any help would be appreciated. Thanks.
This is my code:
static class Receiver
{
public static object thisLock = new object();
public static int success;
public static bool hasLocked()
{
if(Monitor.TryEnter(thisLock))
{
Monitor.Enter(thisLock);
System.Threading.Thread.Sleep(10);
success++;
Monitor.Exit(thisLock);
return true;
}
return false;
}
}
It is legal for the same thread to invoke Enter more than once without it blocking; however, an equal number of Exit calls must be invoked before other threads waiting on the object will unblock.
http://msdn.microsoft.com/en-us/library/de0542zz%28v=vs.110%29.aspx
Basically, you're acquiring the lock two times in your code. You need to remove the call to Monitor.Enter since Monitor.TryEnter already acquired the lock.
static class Receiver
{
public static object thisLock = new object();
public static int success;
public static bool hasLocked()
{
if(Monitor.TryEnter(thisLock))
{
System.Threading.Thread.Sleep(10);
success++;
Monitor.Exit(thisLock);
return true;
}
return false;
}
}
You're acquiring the locks twice, but only releasing it once.
If TryEnter succeeds then you will have acquired the lock. This means you don't need to explicitly acquire it again. However, you do need to release it explicitly. So your code should look like this:
static class Receiver
{
public static object thisLock = new object();
public static int success;
public static bool hasLocked()
{
if(Monitor.TryEnter(thisLock))
{
System.Threading.Thread.Sleep(10);
success++;
Monitor.Exit(thisLock);
return true;
}
return false;
}
}
Monitors are reenterant, so you can acquire them multiple times. However, you must remember to release them by the same number, otherwise they will stay locked.
Related
Is this possible to lock method for one thread and force another to go futher rather than waiting until first thread finish? Can this problem be resolved with static thread or some proper pattern with one instance of mendtioned below service.
For presentation purposes, it can be done with static boolen like below.
public class SomeService
{
private readonly IRepository _repo;
public SomeService(IRepository repo)
{
_repo = repo;
}
private Thread threadOne;
public static bool isLocked { get; set; }
public void StartSomeMethod()
{
if(!isLocked)
{
threadOne = new Thread(SomeMethod);
isLocked = true;
}
}
public void SomeMethod()
{
while(true)
{
lots of time
}
...
isLocked = false;
}
}
I want to avoid situation when user clicked, by accident, two times to start and accidentailly second thread starts immediatelly after first finished.
You can use lock :)
object locker = new object();
void MethodToLockForAThread()
{
lock(locker)
{
//put method body here
}
}
Now the result will be that when this method is called by a thread (any thread) it puts something like flag at the beginning of lock: "STOP! You are not allowed to go any further, you must wait!" Like red light on crossroads.
When thread that called this method first, levaes the scope, then at the beginning of the scope this "red light" changes into green.
If you want to not call the method when it is already called by another thread, the only way to do this is by using bool value. For example:
object locker = new object();
bool canAccess = true;
void MethodToLockForAThread()
{
if(!canAccess)
return;
lock(locker)
{
if(!canAccess)
return;
canAccess = false;
//put method body here
canAccess = true;
}
}
Other check of canAccess in lock scope is because of what has been told on comments. No it's really thread safe. This is kind of protection that is advisible in thread safe singleton.
EDIT
After some discussion with mjwills I have to change my mind and turn more into Monitor.TryEnter. You can use it like that:
object locker = new object();
void ThreadMethod()
{
if(Monitor.TryEnter(locker, TimeSpan.FromMiliseconds(1))
{
try
{
//do the thread code
}
finally
{
Monitor.Exit(locker);
}
} else
return; //means that the lock has not been aquired
}
Now, lock could not be aquired because of some exception or because some other thread has already acuired it. In second parameter you can pass the time that a thread will wait to acquire a lock. I gave here short time because you don't want the other thread to do the job, when first is doing it.
So this solution seems the best.
When the other thread could not acquire the lock, it will go further instead of waiting (well it will wait for 1 milisecond).
Since lock is a language-specific wrapper around Monitor class, you need Monitor.TryEnter:
public class SomeService
{
private readonly object lockObject = new object();
public void StartSomeMethod()
{
if (Monitor.TryEnter(lockObject))
{
// start new thread
}
}
public void SomeMethod()
{
try
{
// ...
}
finally
{
Monitor.Exit(lockObject);
}
}
}
You can use a AutoResetEvent instead of your isLocked flag.
AutoResetEvent autoResetEvent = new AutoResetEvent(true);
public void StartSomeMethod()
{
if(autoResetEvent.WaitOne(0))
{
//start thread
}
}
public void SomeMethod()
{
try
{
//Do your work
}
finally
{
autoResetEvent.Set();
}
}
This block of code is being accessed by many threads
// All code is from same class
public void ExecuteCommand(IAsciiCommand command, IAsciiCommandSynchronousResponder responder)
{
lock (commander)
{
if (commander.IsConnected)
{
commander.ExecuteCommand(command, responder);
}
}
}
public void Disconnect()
{
var tmp = commander.IsConnected;
commander.Disconnect();
if (commander.IsConnected != tmp && !commander.IsConnected)
{
OnPropertyChanged("IsConnected");
}
}
And eventually i get this:
How is this possible, that thread accessed into if statement, whose condition returns false? How can i fix it?
This is happening because the check and the call lack atomicity. Here is a sequence of events that could lead to an exception:
Two threads, A and B, are reaching the condition at the same time
Thread A checks the condition, which returns true, so it enters the if block
At the same time, thread scheduler decides that thread A has exhausted its time slot, and suspends it
Thread B calls Disconnect
Thread scheduler resumes thread A, which is inside the if condition. However, the command is no longer connected
This causes the exception
You can fix it by locking commander inside Disconnect().
public void Disconnect()
{
bool doEvent;
lock(commander) {
var tmp = commander.IsConnected;
commander.Disconnect();
doEvent = (commander.IsConnected != tmp && !commander.IsConnected)
}
// Run OnPropertyChanged outside the locked context
if (doEvent)
{
OnPropertyChanged("IsConnected");
}
}
You need to lock on a static object. Right now you're creating separate locks based on the object your are working with (commander). Try this:
public class WhatEverClassHasTheExecuteCommandMethod
{
private static object _lock = new object();
public void ExecuteCommand(IAsciiCommand command, IAsciiCommandSynchronousResponder responder)
{
lock (_lock)
if (commander.IsConnected)
commander.ExecuteCommand(command, responder);
}
}
If you are not locking while disconnecting, it's entirely possible to get a race condition. The basic solution is to add a lock inside the Disconnect method:
public void Disconnect()
{
lock (commander)
{
var tmp = commander.IsConnected;
commander.Disconnect();
if (commander.IsConnected != tmp && !commander.IsConnected)
OnPropertyChanged("IsConnected");
}
}
When multithreading I know that I need to lock variables if doing things like adding and item to a list etc or I would get a cross thread exception. But do I need to lock them when just assigning variables? I don't mind about if a thread getting an old instance of the variable - I just don't want it to error. Here is an example of what I mean:
public void Run()
{
var thread1 = new Thread(new ThreadStart(Test));
var thread2 = new Thread(new ThreadStart(Test));
thread1.Start();
thread2.Start();
}
private static int _test;
private void Test()
{
while (true)
{
_test += 1;
}
}
If you're just assigning an int, then no. But here you're not just assigning. You're incrementing. So you need some kind of synchronization.
In you want to increment, use Interlocked.Increment:
Interlocked.Increment(ref _test);
Running the code should give you your answer... instead of while(true) write for(i=1;1<1e6;i++) , write the result to screen and run it.
You'll see it does not add up to 2e6, but rather something around 1.2e6. So yes, you need to lock if you want to get out 2e6.
Don't just hypothesize, after that always test and assert.
You have to remember the thread could also be looking at a stale copy, by locking you assure that the version of the variable you are looking at is being refreshed
When I first started coding and thought that maybe I don't need the freshest copy of the variable I would get stuck in infinite loops because I assume the variable would be updated eventually, but if the variable was cached then it would never update
I included examples with brief descriptions, don't worry about the way the thread is started, that is not relevant
private static bool _continueLoop = true;
private static readonly object _continueLoopLock = new object();
private static void StopLoop()
{
lock(_continueLoopLock)
_continueLoop = false;
}
private static void ThreadALoopWillGetStales()
{
while(_continueLoop)
{
//do stuff
//this is not guaranteed to end
}
}
private static void ThreadALoopEventuallyCorrect()
{
while(true)
{
bool doContinue;
lock(_continueLoopLock)
doContinue = _continueLoop;
if(!doContinue)
break;
//do stuff
//this will sometimes result in a stale value
//but will eventually be correct
}
}
private static void ThreadALoopAlwaysCorrect()
{
while(true)
{
bool doContinue;
lock(_continueLoopLock)
if(!_continueLoop)
break;
//do stuff
//this will always be correct
}
}
private static void ThreadALoopPossibleDeadlocked()
{
lock(_continueLoopLock)
while(_continueLoop)
{
//if you only modify "_continueLoop"
//after Acquiring "_continueLoopLock"
//this will cause a deadlock
}
}
private static void StartThreadALoop()
{
ThreadPool.QueueUserWorkItem ((o)=>{ThreadALoopWillGetStales();});
}
private static void StartEndTheLoop()
{
ThreadPool.QueueUserWorkItem((o)=>
{
//do stuff
StopLoop();
});
}
public static void Main(string[] args)
{
StartThreadALoop();
StartEndTheLoop();
}
when you start the loop there is a chance that you will continue to get a stale copy of the variable, that is why you do need some sort of synchronization when accessing a across multiple threads
The method below should return true for the first call, and false for any other call.
Is there any problem with it? Is it safe to use the reset event for locking?
private ManualResetEvent _resetEvent = new ManualResetEvent(false);
public bool AmIFirst()
{
lock (_resetEvent)
{
bool first = !_resetEvent.WaitOne(0);
if (first)
_resetEvent.Set();
return first;
}
}
Edit: I made some changes after reviewing you're remarks. I was stuck on ManualResetEvent due to former design idea. I actually don't need it at all.
class ActionSynchronizer
{
private Timer _expirationTimer;
private object _locker = new object();
private bool _executionRequired = true;
private SomeDelegate _onExpired = delegate { };
public ActionSynchronizer(SomeDelegate onExpired)
{
_onExpired = onExpired;
expirationTimer = new Timer(OnExpired, null, 30000, Timeout.Infinite);
}
public bool IsExecutionRequired()
{
if (!_executionRequired)
return false;
lock (_locker)
{
if (_executionRequired)
{
_executionRequired = false;
return true;
}
return false;
}
}
private void OnExpired(object state)
{
if (_executionRequired)
{
lock (_locker)
{
if (_executionRequired)
{
_executionRequired = false;
// http://stackoverflow.com/questions/1712741/why-does-asynchronous-delegate-method-require-calling-endinvoke/1712747#1712747
_onExpired.BeginInvoke(_originalAction, EndInvoke, null);
}
}
}
}
}
// ...
{
if (_action.Sync.IsExecutionRequired())
_action.Invoke();
}
I would go a different route here...
private int counter;
...
if(Interlocked.Increment(ref counter) == 1)
{
// yes, I'm first
}
Thread safe, no locks. Or if you are worried about wrapping around Int32:
if(Interlocked.CompareExchange(ref counter, 1, 0) == 0)
{
// yes, I'm first
}
Nowadays, I only ever lock() on a simple System.Object object which I've created just for locking with.
I definitely wouldn't lock() on something like an Event, not because it wouldn't work, but because I think it's potentially rather confusing to be using lock() on an object which it is itself (though completely separately) associated with kernel locking type operations.
I'm not clear what you're actually doing here, but it looks rather like something which a named Mutex might do better.
I think it's better to use lock() for this on an object.
Also, you can prevent excess thread locking by using a "double-checked locking"
e.g.
private object _protection = new object();
private bool _firstTime = true;
public bool AmIFirst()
{
if (!_firstTime)
return false;
lock (_protection)
{
if (!_firstTime)
return false;
_firstTime = false;
return true;
}
}
Note... - there's some interesting comments on double-checked locking - Double-checked locking in .NET - I'm still reading up on this!
Another note... its not clear from the code snippet you posted, but if you are looking to implement a global singleton then solution 4 on http://www.yoda.arachsys.com/csharp/singleton.html is a good place to start
The only thing you need to make sure is that the same object you lock on is accessible to all instances of the code that needs synchronizing. Other than that, no problem.
In previous question of mine, someone had meantioned that using Semaphores were expensive in C# compared to using a monitor. So I ask this, how can I replace the semaphore in this code with a monitor?
I need function1 to return its value after function2 (in a separate thread) has been completed. I had replaced the Semaphore.WaitOne with a Monitor.Wait and the Semaphore.Release with a Monitor.PulseAll but the PulseAll was being triggered before the Wait causing the program to hang. Any idea how to avoid that race condition?
Semaphore semaphore = new Semaphore(0,1);
byte b;
public byte Function1()
{
// new thread starting in Function2;
semaphore.WaitOne();
return b;
}
public void Function2()
{
// do some thing
b = 0;
semaphore.Release();
}
You can do this with a WaitHandle instead of a Semaphore. This would be the simplest alternative, and perform better than a Semaphore:
ManualResetEvent manualResetEvent = new ManualResetEvent(false);
byte b;
public byte Function1()
{
// new thread starting in Function2;
manualResetEvent.WaitOne();
return b;
}
public void Function2()
{
// do some thing
b = 0;
manualResetEvent.Set();
}
#Reed provided an elegant solution if you need to wait for multiple threads.
You might not want to use Monitor fro this.
As #Reed pointed out, an event would suffice and would provide the cleanest and most understandable solution that matches the requirements of your code.
The overhead of using real operating system sync primitives will most probably not matter in your case and using e.g. Monitor would provide only diminishing returns at the cost of much higher complexity.
With that said, here is an implementation using Monitor and signaling.
You can use a bool flag - guarded by the lock - to indicate that you have finished and avoid waiting in that case. (A)
If you really start a new thread within Function2() where the comments indicate and use lock() around both WaitOne() and Release(), you do not need the flag at all. (B)
A, using a flag:
class Program
{
static object syncRoot = new object();
//lock implies a membar, no need for volatile here.
static bool finished = false;
static byte b;
public static byte Function1()
{
lock (syncRoot)
{
//Wait only if F2 has not finished yet.
if (!finished)
{
Monitor.Wait(syncRoot);
}
}
return b;
}
static public void Function2()
{
// do some thing
b = 1;
lock (syncRoot)
{
finished = true;
Monitor.Pulse(syncRoot);
}
}
static void Main(string[] args)
{
new Thread(Function2).Start();
Console.WriteLine(Function1());
}
}
B, starting a thread from Function1:
class Program
{
static object syncRoot = new object();
static byte b;
public static byte Function1()
{
lock (syncRoot)
{
// new thread starting in Function2;
new Thread(Function2).Start();
Monitor.Wait(syncRoot);
}
return b;
}
static public void Function2()
{
// do some thing
b = 1;
//We need to take the lock here as well
lock (syncRoot)
{
Monitor.Pulse(syncRoot);
}
}
static void Main(string[] args)
{
Console.WriteLine(Function1());
}
}