Exception on Monitor.Exit in C# - c#

This is a large multi-threaded project (which I didn't write) that I am fixing. The application hangs on some locks which I am tracking down.
I went through and replaced all the "lock" statements with Monitor.TryEnter so I could set a wait period. I am occasionally getting an exception with the Monitor.Exit.
The original style was
private List<myClass> _myVar= new List<myClass>();
if (_myVar != null)
{
lock (_myVar)
{
_myVar = newMyVar; // Where newMyVar is another List<myClass>
}
}
I replaced all my locks like above with:
if (_myVar != null)
{
bool lockTaken = false;
try
{
Monitor.TryEnter(_myVar, new TimeSpan(0, 0, 5), ref lockTaken);
if (lockTaken)
{
_myVar = newMyVar; // Where newMyVar is another List<myClass>
}
}
finally
{
if (lockTaken) Monitor.Exit(_myVar);
}
}
The exception I am getting is
SynchronizationLockException Object synchronization method was called
from an unsynchronized block of code
. If this is true, why doesn't the original lock statement also throw an exception?
Would it be safe to put the Monitor.Exit in a try catch and just ignore it if there is an exception?

It should be very clear why you are getting the exception in your new code. If the lock is taken then the object that is unlocked is not the object that was locked. Locks take an object, not a variable. The correct translation of the deeply wrong original code is
// THIS CODE IS COMPLETELY WRONG; DO NOT USE IT
if (_myVar != null)
{
bool lockTaken = false;
var locker = _myVar;
try
{
Monitor.TryEnter(locker, new TimeSpan(0, 0, 5), ref lockTaken);
if (lockTaken)
{
_myVar = newMyVar; // where newMyVar is another List<myClass>
}
}
finally
{
if (lockTaken) Monitor.Exit(locker);
}
}
Which will not throw on exit, but is still completely wrong.
Never lock on the contents of a variable and then mutate the variable; every subsequent lock will lock on a different object! So you have no mutual exclusion.
And never lock on a public object! If that list leaks out anywhere then other wrong code can be locking on that list in an unexpected order, which means deadlocks -- which is the original symptom you are diagnosing.
The correct practice for locking on a field is to create a private readonly object field used only as a locker, and used every time the field is accessed. That way you know that (1) the field is always accessed under the same lock, no matter its value, and (2) the lock object is used only for locking that field, and not for locking something else. That ensures mutual exclusion and prevents deadlocks.
The fact that someone wrote a large multithreaded program without understanding the most basic facts about locks means that it is almost certainly a complete mess of hard-to-find bugs. The fact that this wasn't immediately obvious upon reading the code means that you don't have enough knowledge of threading to fix the problems correctly. You're going to need to either find an expert on this stuff who can help you, or gain at least a minimal working knowledge of correct practices.
I cannot emphasize enough that this is hard stuff. Programs with multiple threads of control in them are extremely difficult to write correctly on modern hardware; many of the things you believe are guaranteed by the language are only guaranteed in single threaded programs.

Related

Should I use a boolean variable to indicate whether a lock has been acquired?

I am currently building a multi-threaded software (in C#), and I am not sure about my solution for a problem.
// isLocked is initialized at earlier stage
if (!isLocked)
{
isLocked = true;
// More code here
}
I know that the condition check is atomic, but i think its possible that another thread will enter the if block before 'isLocked' is assigned the 'true' value (thus creating an unwanted situation).
In Java, i could use AtomicBoolean's method 'compareAndSet' which is atomic, but C#'s equivalent 'CompareExchange' is not atmoic.
I tried using a bool in addition to the lock so that if the "locked" code is already being executed, other threads will bypass it. Is this a good way to do that, or is there a better way?
Object myLock = new object();
bool free = false;
bool isLocked= actorsLocks[i];// Some Data structure
if (!isLocked)
{
lock(mylock)
{
if (!isLocked)
{
isLocked= true;
free = true;
}
}
}
if(free)
{
// actual method code here...
}
Is there a more efficient solution?
Thank you very much in advance.
In Java, i could use AtomicBoolean's method 'compareAndSet' which is
atomic, but C#'s equivalent 'CompareExchange' is not atmoic.
...Uh... yeah it is. Otherwise it would be completely useless.
https://msdn.microsoft.com/en-us/library/801kt583(v=vs.110).aspx#Anchor_2
If comparand and the value in location1 are equal, then value is
stored in location1. Otherwise, no operation is performed. The compare
and exchange operations are performed as an atomic operation. The
return value of CompareExchange is the original value in location1,
whether or not the exchange takes place.
Your solution is close. Make sure your lock object and all variables it protects are accessible by all threads. It won't do you any good to lock a locally-declared object. For example, myLock could be a class data member. It definitely should not be declared in the function. Same thing goes for isLocked.
class C
{
int[] m_actorsLocks; // *See below
...
void WorkerFunction(int threadIndex)
{
if (CompareExchange(ref m_actorsLocks[threadIndex], 1, 0) == 0) // cmpxchg returns old value. If old value was false, it means WE locked it!
{
// do work
// use cmpxchg to free the lock
CompareExchange(ref m_actorsLocks[threadIndex], 0, 1)
// I do this simply because I don't understand how C# caches outgoing writes
// could possibly do m_actorsLocks[threadIndex] = 0; surrounded by Interlocked.MemoryBarrier()
}
else
{
// Threads who didn't get the lock come here...
// If I understand what you're trying to do, you don't want the other threads to wait if they didn't get the lock.
// So you probably wouldn't need this else clause...
}
}
...
};
*If you store your locks in an array, you'll experience false sharing. Since arrays are stored contiguously, your locks will be on the same cache line... you would have the same performance as if you used 1 lock for everything. The grungy way to deal with this is to pad out your array. For example:
// If I want 4 locks
int[] m_actorsLocks = new int[32];
// Now i only use index 0, 8, 16, and 24. The rest are just padding.
It's kinda messy and requires knowlege of your architecture... Better do some research on this one and maybe ask a seperate question.
All you need in C# is:
object theLock = new Object();
lock(theLock)
{
// Lock is yours, enjoy
}
If you want to both attempt to acquire the lock and find out whether you acquired it, in one atomic operation, use Monitor.TryEnter(object).
Monitor.TryEnter returns true if the lock is acquired, false if it isn't. Only execute the "locked" code if TryEnter returns true.
public class SomeClassThatMultipleThreadsAccess
{
private readonly object _lockObject = new object();
public void MethodThatGetsCalledConcurrently()
{
if(Monitor.TryEnter(_lockObject))
{
try
{
// only one thread at a time can execute this in
// one instance of the class.
// If _lockObject is static then only one thread at
// a time can execute this across all instances of
// the class.
}
finally // very important - if we don't exit then nothing else can enter.
{
Monitor.Exit(_lockObject);
}
}
}
}
Note that the object used for locking cannot be declared in the same scope in which it is used.
These both do nothing:
var lockObject = new object();
if(Monitor.TryEnter(lockObject))
var lockObject = new object();
lock(lockObject)
{
because each thread will create a different object, so each thread will immediately acquire the lock. It won't prevent concurrent access to anything ever. There must be one object on which multiple threads attempt to acquire a lock.
In few words: you're asking for trouble. Don't do that.
In more details, there are many factors you underestimate:
CPU conveyor optimization. This means that without proper "do not touch, multiple threads accessing" mark your CPU can modify execution order. And this may do very unexpected things that're absolutely legit in terms of single thread but can ruin your synchronization logic.
Compiler optimization. This can eliminate entire block of code according to Boolean value (and compiler has no idea the bool can be changed by another thread).
False sharing. This is more advanced thing and it can't change your program behavior. However, it can cause significant performance degradation because you read&write your hand-made locks at continuous array (that ruins core-level caches, fastest ones).
This is what can be named right out of the head. If think more, we can find more cons against hand-made thread sync mechanics. So, multithreading is like encryption: do not try to reinvent it, you're dangerously low-informed and would be cracked in minutes or even seconds.
You are right: the read of the bool is atomic but several threads can read atomically the bool and enter the 'if' block before the flag becomes false.
To do what you want (one thread only enters the 'if' block without blocking other threads) you can use kind of :
private long _n = 0;
......
if (Interlocked.Exchange(ref _n, 1) == 0)
{
// More code here, only one thread at a time.
// Be carefull with exceptions.
Interlocked.Exchange(ref _n, 0); // Reset the flag for next running.
}
The Interlocked.Exchange is an atomic read&write: it will block all the threads, except one which will read '_n=0' and write '_n=1' as an atomic operation. The other threads will got 1 immediatly after the interlocked statment returns and they do not enter the block.

new instance of Object()

I came across this definition of Object constructor (metadata from mscorlib.dll)
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public Object();
I didn't understood what ConstrainedExecution (Cer.MayFail) mean can someone tell me with an example in this case.
I came across this code, also tell me if it is correct to write like this,
public class MyClass
{
private static object instanceLock = new object();
private void Func()
{
bool instanceLockTaken = false;
Monitor.TryEnter(instanceLock, ref instanceLockTaken);
//...
Monitor.Exit(instanceLock);
}
}
Constrained Execution is what you're trying to achieve by locking the thread.
From: http://msdn.microsoft.com/en-us/magazine/cc163716.aspx
A Cer value of MayFail is used to signal that when faced with
asynchronous exceptions, the code may not complete in an expected
fashion. Since thread aborts are being delayed over constrained
execution regions, this really means that your code is doing something
that may cause memory to be allocated or that might result in a stack
overflow. More importantly, it means that you must take the possible
failures into consideration when calling this method.
In your case, because the object is static and only created once, this will not be a problem.
Monitor.TryEnter returns immediately even if a lock was not acquired. It has a boolean value, which you're not checking, something like this would work:
Monitor.TryEnter(instanceLock, ref instanceLockTaken);
if (instanceLockTaken)
{
// Do stuff here
Monitor.Exit(instanceLock);
}
However, this code would mean that the if {} block would not be executed every time, if you want to acquire a lock on every thread, you'll need to do something like this:
lock(instanceLock)
{
// Do stuff here
}
This means that only a single thread can run the contents of the lock {} statement at a time, and the contents of the lock statement will be executed every time.
On a side note, you can also make the object you're locking readonly:
private static readonly object instanceLock = new object();
So, generally speaking, you have 2 questions here.
1) Reliability contracts is a tool used by CLR team to support constrained execution regions. It is an advanced topic, but simply speaking the construction describes if a function (or a constructor) can fail, and if yes, what impact will be ( no impact, appDomain impact, process impact, whole machine crush, etc)
2) Your code snippet is incorrect. Why do you saving instanceLockTaken if you are not going to check it further? Furthermore, if exception occur between the lock acquisition and releasing it, you'll leak the lock.
Consider using the lock statement, which is syntax sugar for something like this:
bool instanceLockTaken = false;
try
{
Monitor.Enter(instanceLock, ref instanceLockTaken);
//...
}
finally
{
if (instanceLockTaken)
{
Monitor.Exit(instanceLock);
}
}
Cer.Mayfail keyword implies that if the marked method throws an exception, the data may be in an invalid state; the previous state of the object will not be restored.
This is the correct way for Monitor locking;
bool isLocked = false;
try
{
Monitor.Enter(instanceLock , ref isLocked);
// Do some things within the lock
}
finally
{
if (isLocked) Monitor.Exit(instanceLock);
}
As for cer.mayfail this link will provide some more information http://weblogs.asp.net/justin_rogers/archive/2004/10/05/238275.aspx

ReaderWriterLockSection: A bad idea?

In writing some threaded code, I've been using the ReaderWriterLockSlim class to handle synchronized access to variables. Doing this, I noticed I was always writing try-finally blocks, the same for each method and property.
Seeing an opportunity to avoid repeating myself and encapsulate this behaviour I built a class, ReaderWriterLockSection, intended to be used as a thin wrapper to the lock which can be used with the C# using block syntax.
The class is mostly as follows:
public enum ReaderWriterLockType
{
Read,
UpgradeableRead,
Write
}
public class ReaderWriterLockSection : IDisposeable
{
public ReaderWriterLockSection(
ReaderWriterLockSlim lock,
ReaderWriterLockType lockType)
{
// Enter lock.
}
public void UpgradeToWriteLock()
{
// Check lock can be upgraded.
// Enter write lock.
}
public void Dispose()
{
// Exit lock.
}
}
I use the section as follows:
private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim();
public void Foo()
{
using(new ReaderWriterLockSection(_lock, ReaderWriterLockType.Read)
{
// Do some reads.
}
}
To me, this seems like a good idea, one that makes my code easier to read and seemingly more robust since I wont ever forget to release a lock.
Can anybody see an issue with this approach? Is there any reason this is a bad idea?
Well, it seems okay to me. Eric Lippert has previously written about the dangers of using Dispose for "non-resource" scenarios, but I think this would count as a resource.
It may make life tricky in upgrade scenarios, but you could always fall back to a more manual bit of code at that point.
Another alternative is to write a single lock acquire/use/release method and provide the action to take while holding the lock as a delegate.
I usually indulge into this kind of code-sugary confections!
Here's a variant that's a bit easier to read for the users, on top of your API
public static class ReaderWriterLockExt{
public static IDisposable ForRead(ReaderWriterLockSlim rwLock){
return new ReaderWriterLockSection(rwLock,ReaderWriterLockType.Read);
}
public static IDisposable ForWrite(ReaderWriterLockSlim rwLock){
return new ReaderWriterLockSection(rwLock,ReaderWriterLockType.Write);
}
public static IDisposable ForUpgradeableRead(ReaderWriterLockSlim wrLock){
return new ReaderWriterLockSection(rwLock,ReaderWriterLockType.UpgradeableRead);
}
}
public static class Foo(){
private static readonly ReaderWriterLockSlim l=new ReaderWriterLockSlim(); // our lock
public static void Demo(){
using(l.ForUpgradeableRead()){ // we might need to write..
if(CacheExpires()){ // checks the scenario where we need to write
using(l.ForWrite()){ // will request the write permission
RefreshCache();
} // relinquish the upgraded write
}
// back into read mode
return CachedValue();
} // release the read
}
}
I also recommend using a variant that takes an Action delegate that's invoked when the lock cannot be obtained for 10 seconds, which I'll leave as an exercise to the reader.
You might also want to check for a null RWL in the static extension methods, and make sure the lock exists when you dispose it.
Cheers,
Florian
There is another consideration here, you are possibly solving a problem you should not solve. I can't see the rest of your code but I can guess from you seeing value in this pattern.
Your approach solves a problem only if the code that reads or writes the shared resource throws an exception. Implicit is that you don't handle the exception in the method that does the reading/writing. If you did, you could simply release the lock in the exception handling code. If you don't handle the exception at all, the thread will die from the unhandled exception and your program will terminate. No point in releasing a lock then.
So there's a catch clause somewhere lower in the call stack that catches the exception and handles it. This code has to restore the state of the program so that it can meaningful continue without generating bad data or otherwise die due to exceptions caused by altered state. That code has a difficult job to do. It needs to somehow guess how much data was read or written without having any context. Getting it wrong, or only partly right, is potentially very destabilizing to the entire program. After all, it was a shared resource, other threads are reading/writing from it.
If you know how to do this, then by all means use this pattern. You better test the heck out of though. If you're not sure then avoid wasting system resources on a problem you can't reliably fix.
One thing I'd suggest when wrapping a lock to facilitate the "using" pattern is to include a "danger-state" field in the lock; before allowing any code to enter the lock, the code should check the danger state. If the danger state is set, and the code which is trying to enter the lock hasn't passed a special parameter saying it's expecting that it might be, the attempt to acquire the lock should throw an exception. Code which is going to temporarily put the guarded resource into a bad state should set the danger state flag, do what needs to be done, and then reset the danger state flag once the operation is complete and the object is in a safe state.
If an exception occurs while the danger state flag is set, the lock should be released but the danger state flag should remain set. This will ensure that code which wants to access the resource will find out that the resource is corrupted, rather than waiting forever for the lock to be released (which would be the outcome if there were no "using" or "try-finally" block).
If the lock being wrapped is a ReaderWriterLock, it may be convenient to have the acquisition of a "writer" lock automatically set the danger state; unfortunately, there's no way for an IDisposable used by a using block to determine whether the block is being exited cleanly or via exception. Consequently, I don't know any way to use something syntactically like a 'using' block to guard the "danger state" flag.

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