c# threads synchronisation - c#

I need to use lock object, but it is already used by another thread. I wish to wait while the lock object will be free but have no idea how to do this.
I found sth like:
if(Monitor.TryEnter(_lock)
{
try
{
// do work
}
finally
{
Monitor.Exit(_lock);
}
}
But I it just check and go on, but I wish to wait until lock object is free.

Either use this:
Monitor.Enter(_lock)
try
{
// do work
}
finally
{
Monitor.Exit(_lock);
}
or - more preferably - the lock keyword:
lock(_lock)
{
// do work
}
In fact, those code snippets will generate the same code. The compiler will translate the second code into the first one. However, the second one is preferred because it is far more readable.
UPDATE:
The lock belongs to the thread it was acquired in. That means, nested usage of the lock statement is possible:
void MethodA()
{
lock(_lock)
{
// ...
MethodB();
}
}
void MethodB()
{
lock(_lock)
{
// ...
}
}
The above code will not block.

You can use Monitor.Enter
From docs:
Use Enter to acquire the Monitor on the object passed as the
parameter. If another thread has executed an Enter on the object but
has not yet executed the corresponding Exit, the current thread will
block until the other thread releases the object.

I agree with #Daniel Hilgarth, the lock syntax is preferred.
Regarding your question:
I wish to wait while the lock object will be free but have no idea how to do this.
As per the MSDN description:
lock ensures that one thread does not enter a critical section while another thread is in the critical section of code. If another thread attempts to enter a locked code, it will wait (block) until the object is released.
i.e. the code you have already does what you want it to.

Related

Skip SemaphoreSlim instead of wait

I have a part of code in an Async/Await function that I only want one thread to execute at a time.
This is relatively simple by creating a new SemaphoreSlim(1) and using WaitAsync/Release. The effect is that the first thread executes while the others wait and then execute one by one.
What I am trying to achieve is actually slightly different. I would like the other threads not to wait, but to return out of the function (i.e. I don't want to block the other threads). So if there was a property "NumberOfThreadsCurrentlyExecuting" I would effectively have an If Semaphore.NumberOfThreadsCurrentlyExecuting > 0 Then Return.
But such a property doesn't exist. Does anyone have any idea for a way around this problem?
Thanks
Charles
How about using the SemaphoreSlim.Wait/Async with a zero-timeout? If it can't enter the semaphore (because it's already been entered), it will return false.
Note that Monitor (and thus lock) is completely unsuited to async
(hence the fact that you can't await in a lock) because
your task may continue on another thread after you've entered the lock (thus you will try to release the lock from another thread)
after you've awaited, another continuation may use your thread (while it is still holding the lock), so if it attempts to acquire the lock it will succeed
Instead of a Semaphore, you could just use a Monitor.
If you call TryEnter and it fails, another thread is in the "lock".
This is thread safe (unlike checking semaphore counts), and fairly simple:
// using somethign like: object sync = new object();
bool lockTaken = Monitor.TryEnter(sync);
try
{
if (lockTaken)
{
// You're here - do your work
}
else
{
// Something else was in the thread - exit?
return;
}
}
finally
{
if (lockTaken) Monitor.Exit(sync);
}

lock inside lock

I'm wondering if this construction will cause an error:
lock(sync)
{
// something
lock(sync)
{
//something
lock(sync)
{
//something
}
}
}
I've run this code, and it seems fine, but maybe in some circumstances an error may be thrown?
lock is a wrapper for Monitor.Enter and Monitor.Exit:
The lock keyword calls Enter at the start of the block and Exit at the end of the block. From the former's documentation:
From the documentation for Monitor.Enter:
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.
Because the calls to Enter and Exit are paired, your code pattern has well defined behaviour.
Note, however, that lock is not guaranteed to be an exception-less construct:
A ThreadInterruptedException is thrown if Interrupt interrupts a thread that is waiting to enter a lock statement.
To explain why it is well-defined behavior and will never fail:
Aside: This answer has better details about how locks actually work
The lock occurs at the Thread level, so calling it a second time on the same thread will be redundant. I would think it would not have any performance penalty (although that would depend on how exactly the internals of .Net are written, so I can't guarantee that)
Many times you'd have a public function that calls another public function in your class, whom both need the lock when used seperately. If this was not allowed the following would fail:
private Dictionary<string, int> database = new Dictionary<string, int>();
private object databaseLock = new object();
public void AddOrUpdate(string item)
{
lock (databaseLock)
{
if (Exists(item))
database.Add(item, 1);
else
++database[item];
}
}
public bool Exists(string item)
{
lock (databaseLock)
{
//... Maybe some pre-processing of the key or item...
return database.ContainsKey(item);
}
}
According to MSDN (see here and here) this is well-defined behaviour and causes no problem.

Multiple code blocks locked by the same object

If I have something like this:
private readonly object objectLock = new object();
public void MethodA()
{
lock(objectLock)
{
//do something
}
}
public void MethodB()
{
lock(objectLock)
{
//do something
}
}
If I have 2 threads and both come in at the same time, 1st thread calls MethodA and second Method B. Whichever gets there first and locks objectLock, I assume the other thread sits there waiting until objectLock is no longer locked.
Yes, your explanation is right -- unless the lock is already taken (in which case both threads sit waiting, and an arbitrary one gets the lock as soon as it's unlocked).
(Slightly offtopic) I would advise not to lock the whole methods if they are doing something non-trivial. Try to keep the "locking" section of code as small and as fast as possible.
That is correct.
However it is not the objectLock that is locked (nor the object) it is the code blocks that are locked.
Think of the object that is passed to the lock keyword as a key that does unlock multiple doors but only grants access to a single room at one time.
You're absolutely right! But be careful with locks. Locks will maybe make you're program thread-safe (means, no errors on concurrent accesses) but it takes much more effort making make your program taking real advantage from running on a multi-kernel system.
yes you are right as Monitor.Enter and Monitor.Exit is called on same object objectLock behind the scene. remember its the code block that is synchronized not the objectLock.
You're correct. If this isn't desirable, then consider that:
lock(objectLock)
{
//do something
}
Is equivalent to:
Monitor.Enter(objectLock);
try
{
//do something
}
finally
{
Monitor.Exit(objectLock);
}
You can replace this with:
if(Monitor.TryEnter(objectLock, 250))//Don't wait more than 250ms
{
try
{
//do something
}
finally
{
Monitor.Exit(objectLock);
}
}
else
{
//fallback code
}
It's also worth looking at the overloads of TryEnter(), and the other synchronisation objects such as ReaderWriterLockSlim.

Does lock(){} lock a resource, or does it lock a piece of code?

I'm still confused... When we write some thing like this:
Object o = new Object();
var resource = new Dictionary<int , SomeclassReference>();
...and have two blocks of code that lock o while accessing resource...
//Code one
lock(o)
{
// read from resource
}
//Code two
lock(o)
{
// write to resource
}
Now, if i have two threads, with one thread executing code which reads from resource and another writing to it, i would want to lock resource such that when it is being read, the writer would have to wait (and vice versa - if it is being written to, readers would have to wait). Will the lock construct help me? ...or should i use something else?
(I'm using Dictionary for the purposes of this example, but could be anything)
There are two cases I'm specifically concerned about:
two threads trying to execute same line of code
two threads trying to work on the same resource
Will lock help in both conditions?
Most of the other answers address your code example, so I'll try to answer you question in the title.
A lock is really just a token. Whoever has the token may take the stage so to speak. Thus the object you're locking on doesn't have an explicit connection to the resource you're trying to synchronize around. As long as all readers/writers agree on the same token it can be anything.
When trying to lock on an object (i.e. by calling Monitor.Enter on an object) the runtime checks if the lock is already held by a thread. If this is the case the thread trying to lock is suspended, otherwise it acquires the lock and proceeds to execute.
When a thread holding a lock exits the lock scope (i.e. calls Monitor.Exit), the lock is released and any waiting threads may now acquire the lock.
Finally a couple of things to keep in mind regarding locks:
Lock as long as you need to, but no longer.
If you use Monitor.Enter/Exit instead of the lock keyword, be sure to place the call to Exit in a finally block so the lock is released even in the case of an exception.
Exposing the object to lock on makes it harder to get an overview of who is locking and when. Ideally synchronized operations should be encapsulated.
Yes, using a lock is the right way to go. You can lock on any object, but as mentioned in other answers, locking on your resource itself is probably the easiest and safest.
However, you may want use a read/write lock pair instead of just a single lock, to decrease concurrency overhead.
The rationale for that is that if you have only one thread writing, but several threads reading, you do not want a read operation to block an other read operation, but only a read block a write or vice-versa.
Now, I am more a java guy, so you will have to change the syntax and dig up some doc to apply that in C#, but rw-locks are part of the standard concurrency package in Java, so you could write something like:
public class ThreadSafeResource<T> implements Resource<T> {
private final Lock rlock;
private final Lock wlock;
private final Resource res;
public ThreadSafeResource(Resource<T> res) {
this.res = res;
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
this.rlock = rwl.readLock();
this.wlock = rwl.writeLock();
}
public T read() {
rlock.lock();
try { return res.read(); }
finally { rlock.unlock(); }
}
public T write(T t) {
wlock.lock();
try { return res.write(t); }
finally { wlock.unlock(); }
}
}
If someone can come up with a C# code sample...
Both blocks of code are locked here. If thread one locks the first block, and thread two tries to get into the second block, it will have to wait.
The lock (o) { ... } statement is compiled to this:
Monitor.Enter(o)
try { ... }
finally { Monitor.Exit(o) }
The call to Monitor.Enter() will block the thread if another thread has already called it. It will only be unblocked after that other thread has called Monitor.Exit() on the object.
Will lock help in both conditions?
Yes.
Does lock(){} lock a resource, or does
it lock a piece of code?
lock(o)
{
// read from resource
}
is syntactic sugar for
Monitor.Enter(o);
try
{
// read from resource
}
finally
{
Monitor.Exit(o);
}
The Monitor class holds the collection of objects that you are using to synchronize access to blocks of code.
For each synchronizing object, Monitor keeps:
A reference to the thread that currently holds the lock on the synchronizing object; i.e. it is this thread's turn to execute.
A "ready" queue - the list of threads that are blocking until they are given the lock for this synchronizing object.
A "wait" queue - the list of threads that block until they are moved to the "ready" queue by Monitor.Pulse() or Monitor.PulseAll().
So, when a thread calls lock(o), it is placed in o's ready queue, until it is given the lock on o, at which time it continues executing its code.
And that should work assuming that you only have one process involved. You will want to use a "Mutex" if you want that to work across more then one process.
Oh, and the "o" object, should be a singleton or scoped across everywhere that lock is needed, as what is REALLY being locked is that object and if you create a new one, then that new one will not be locked yet.
The way you have it implemented is an acceptable way to do what you need to do. One way to improve your way of doing this would be to use lock() on the dictionary itself, rather than a second object used to synchronize the dictionary. That way, rather than passing around an extra object, the resource itself keeps track of whether there's a lock on it's own monitor.
Using a separate object can be useful in some cases, such as synchronizing access to outside resources, but in cases like this it's overhead.

Syntax for interruptible lock in C#

I suspect this is a very dumb question: what is the correct syntax for an interruptible lock statement in C#? E.g. get lock; if lock is interrupted before locked code finishes, return false out of the enclosing method. Probably totally the wrong terminology... Thanks.
You can have a timeout while aquiring a lock using Monitor.TryEnter; and likewise, within a lock you can do things like Monitor.Wait/Monitor.Pulse to temporarily yield the lock, but you can't be interrupted as such.
The main time interrupt applies might be in Thread.Sleep, which can be interrupted with Thread.Interrupt - but again, this won't yank control out of an executing method block.
What exactly is it that you are trying to achieve? With more context we can probably help more...
What you mean by "interrupted" is unclear.
Interruption by Exception
private bool SomeLockingMethod(object foo)
{
// Verify foo is valid
try
{
lock(foo)
{
while(something)
{
// Do stuff
Thread.Sleep(1); // Possibly yield to another
// thread calling Thread.Interrupt
}
}
return true;
}
catch(ThreadInterruptedException ex)
{
// Handle exception
}
return false;
}
If the return true isn't reached, then something happened while the lock on foo was held, and the code returns false. The lock is automatically released, either way.
Another thread can interrupt this one by calling Thread.Interrupt.
"Interruption" from code
If you're the one "interrupting" the code, it could be as simple as
private bool SomeLockingMethod(object foo)
{
// Verify foo is valid
lock(foo)
{
// Do stuff
if(shouldInterrupt)
{
return false;
}
// Do more stuff
}
return true;
}
Again, the lock is automatically released, whether or not there is an "interruption".
Interruption because someone else is trying to acquire the lock
Possibly this is what you're looking for; in this case you may want to use something else, like a Semaphore or ManualResetEvent.
I'm not sure what you're trying to get at here. The purpose of the lock statement is that you should not get interrupted so you can ensure consistent behavior.
What are you trying to accomplish here?
You might also have a look at transaction scope, added in 2.0, which may be what you're looking for (unknown, due the ambiguity in your question). It allows you to attempt some actions, then roll back if those actions were not completed properly.
See here for more details.

Categories