rationale behind lock inside lock? - c#

I am reviewing an example code in a book and came across the following code(simplified).
In the code, when Subscribe(T subscriber) is called, the thread enters into a lock section.
and then, when code inside the lock calls AddToSubscribers(T subscriber) method, the method has another lock. why is this second lock necessary?
public abstract class SubscriptionManager<T> where T : class
{
private static List<T> subscribers;
private static void AddToSubscribers(T subscriber)
{
lock (typeof(SubscriptionManager<T>))
{
if (subscribers.Contains(subscriber))
return;
subscribers.Add(subscriber);
}
}
public void Subscribe(T subscriber)
{
lock (typeof(SubscriptionManager<T>))
{
AddToSubscribers(subscriber);
}
}
}

In that context, it isn't; however, since locks are re-entrant that can be useful to ensure that any other caller of AddToSubscribers observes the lock. Actually, for that reason I'd say "remove it from Subscribe and just let AddToSubscribers do the locking".
However! A lock on a Type is pretty dangerous. A field would be safer:
// assuming static is correct
private static readonly object syncLock = new object();
and lock(syncLock). Depending on when subscribers is assigned, you might also get away with lock(subscribers) (and no extra field).
I should also note that having an instance method add to static state is pretty.... unusual; IMO Subscribe should be a static method, since it has nothing to do with the current instance.

In the code you posted, it isn't necessary. But then again, the code you posted is incomplete - for example the subscribers list is never initialized.
Locking on typeof(SubscriptionManager) is probably not a good idea either - locking on the subscribers field would be better - but would require the subscribers field to be initialized, e.g.
private static List<T> subscribers = new List<T>();

You probably should read near that sample and see what book talks about.
For that particular case - no, second lock is unnecessary.
Note: The sample is dangerous since it locks on public object (type). Normally one locks on special private object so external code is not able to mistakenly introduce deadlocks by mistakenly locking on the same object.

I also faced a situation once where I had to use nested Lock.
My case was, the function of the second lock maybe called from elsewhere, since it was a static function. However, for your case it won't be necessary since each data member belongs to an Instance and not static..

Related

Static lock object is not initialized in time

Today I encountered a weird issue in our multi-threaded .NET application.
I was writing a public static event accessor like so:
private static readonly object myLock = new object();
private static Action<MyType, Guid, Guid> _handler;
public static event Action<MyType, Guid, Guid> MyEvent
{
add { lock (myLock) _handler += value; }
remove { lock (myLock) _handler -= value; }
}
This piece of code lives in a a non static class.
The issue I face is that once I use the add accessor (at a rather early point of the execution of the application): MyClass.MyEvent += myMethod;, I get a null reference exception in the lock method call in the add accessor. Through debugging I found out that this is because, for some reason, the private static lock object is (still) null at the point the code reaches the lock statement.
This is baffling to me. My understanding is that all static members should be initialized at the point of the first access to the class? I later did realize, that the code seems to work if I move the lock object to the top of the class, meaning it gets initialized at an way earlier point. This works, but I would like to keep all relevant code in one place, so I don't like this solution.
FYI, the file I am working in has almost 5000 lines of code, and the snippet above is close to the end. I have no idea if that makes any difference though...
A theory of ours has been that the problem has to do with the fact that we are working with several threads. More precise than that, we have not figured out. It feels a bit silly that this would be the cause of or problem, as the reason we want to use a static event accessor with locks is to handle multi-thread access...
UPDATE
So it turns out it now suddenly just works. As it should.
I honestly have no idea what the problem nor the fix was. I simply went on with my day and implemented a few other static event fields as well as subscribing to these from another file. Having recompiled the project it now works as it should. I did not edit the order of the statements in the file btw.
Thank you all for all your suggestions, thoughts and information. I realise the manner of this implementation (public static event) may not be optimal, but it was the route chosen for this implementation for the moment.
From the comments,
"That the compiler generated accessors are not thread safe?" - compiler-generated "field-like events" (i.e.
public static event Action<MyType, Guid, Guid> MyEvent;
are guaranteed by the specification to be thread-safe (the compiler currently uses a looped interlocked exchange, but lock has also been used in the past).
So: you don't actually need anything here. That said, static events are usually a bad idea and can lead to memory leaks. But: we also have a field initialization problem; now, as you suggest, the static field initializer here:
private static object myLock = new object();
should absolutely be ready when it is needed; the runtime guarantees static initializers are executed, so this should be fine; you could try adding readonly to make sure that you don't have code that is accessing it incorrectly, but I have to agree: this code should work fine. A full (but minimal) repro would probably be necessary to investigate it. The other thing (in addition to readonly) that I would be interested in looking for would be other field initializers, that might cause this event to get touched, for example:
private static Foo foo = new Foo();
private static object myLock = new object();
If the Foo() constructor calls back into the event, for example:
class Foo {
public Foo() {
YourType.MyEvent += SomeHandler;
}
}
then the field initializer will not have finished yet, and will not have reached the myLock assignment. The order of static field initializers is preserved, noting that if you have multiple partial class files, then that order is itself not defined. In that scenario, making sure they are ordered correctly should fix it:
// IMPORTANT: make sure this stays first
private static object myLock = new object();
private static Foo foo = new Foo();

Why Locking On a Public Object is a Bad Idea

Ok, I've used locks quite a bit, but I've never had this scenario before. I have two different classes that contain code used to modify the same MSAccess database:
public class DatabaseNinja
{
public void UseSQLKatana
{
//Code to execute queries against db.TableAwesome
}
}
public class DatabasePirate
{
public void UseSQLCutlass
{
//Code to execute queries against db.TableAwesome
}
}
This is a problem, because transactions to the database cannot be executed in parallel, and these methods (UseSQLKatana and UseSQLCutlass) are called by different threads.
In my research, I see that it is bad practice to use a public object as a lock object so how do I lock these methods so that they don't run in tandem? Is the answer simply to have these methods in the same class? (That is actually not so simple in my real code)
Well, first off, you could create a third class:
internal class ImplementationDetail
{
private static readonly object lockme = new object();
public static void DoDatabaseQuery(whatever)
{
lock(lockme)
ReallyDoQuery(whatever);
}
}
and now UseSQLKatana and UseSQLCutlass call ImplementationDetail.DoDatabaseQuery.
Second, you could decide to not worry about it, and lock an object that is visible to both types. The primary reason to avoid that is because it becomes difficult to reason about who is locking the object, and difficult to protect against hostile partially trusted code locking the object maliciously. If you don't care about either downside then you don't have to blindly follow the guideline.
The reason it's bad practice to lock on a public object is that you can never be sure who ELSE is locking on that object. Although unlikely, someone else someday can decide that they want to grab your lock object, and do some process that ends up calling your code, where you lock onto that same lock object, and now you have an impossible deadlock to figure out. (It's the same issue for using 'this').
A better way to do this would be to use a public Mutex object. These are much more heavyweight, but it's much easier to debug the issue.
Use a Mutex.
You can create mutex in main class and call Wait method at the beginning of each class (method); then set mutex so when the other method is called it gonna wait for first class to finish.
Ah, remember to release mutex exiting from those methods...
I see two differing questions here:
Why is it a bad idea to lock on a public object?
The idea is that locking on an object restricts access while the lock is maintained - this means none of its members can be accessed, and other sources may not be aware of the lock and attempt to utilise the instance, even trying to acquire a lock themselves, hence causing problems.
For this reason, use a dedicated object instance to lock onto.
How do I lock these methods so that they don't run in tandem?
You could consider the Mutex class; creating a 'global' mutex will allow your classes to operate on the basis of knowing the state of the lock throughout the application. Or, you could use a shared ReaderWriterLockSlim instance, but I wouldn't really recommend the cross-class sharing of it.
You can use a public LOCK object as a lock object. You'll just have to specify that the object you're creating is a Lock object solely used for locking the Ninja and Pirate class.

locking the object inside a property, c#

public ArrayList InputBuffer
{
get { lock (this.in_buffer) { return this.in_buffer; } }
}
is this.in_buffer locked during a call to InputBuffer.Clear?
or does the property simply lock the in_buffer object while it's getting the reference to it; the lock exits, and then that reference is used to Clear?
No, the property locks the reference while it's getting that reference. Pretty pointless, to be honest... this is more common:
private readonly object mutex = new object();
private Foo foo = ...;
public Foo Foo
{
get
{
lock(mutex)
{
return foo;
}
}
}
That lock would only cover the property access itself, and wouldn't provide any protection for operations performed with the Foo. However, it's not the same as not having the lock at all, because so long as the variable is only written while holding the same lock, it ensures that any time you read the Foo property, you're accessing the most recent value of the property... without the lock, there's no memory barrier and you could get a "stale" result.
This is pretty weak, but worth knowing about.
Personally I try to make very few types thread-safe, and those tend to have more appropriate operations... but if you wanted to write code which did modify and read properties from multiple threads, this is one way of doing so. Using volatile can help too, but the semantics of it are hideously subtle.
The object is locked inside the braces of the lock call, and then it is unlocked.
In this case the only code in the lock call is return this.in_buffer;.
So in this case, the in_buffer is not locked during a call to InputBuffer.Clear.
One solution to your problem, using extension methods, is as follows.
private readonly object _bufLock;
class EMClass{
public static void LockedClear(this ArrayList a){
lock(_bufLock){
a.Clear();
}
}
}
Now when you do:
a.LockedClear();
The Clear call will be done in a lock.
You must ensure that the buffer is only accessed inside _bufLocks.
In addition to what others have said about the scope of the lock, remember that you aren't locking the object, you are only locking based on the object instance named.
Common practice is to have a separate lock mutex as Jon Skeet exemplifies.
If you must guarantee synchronized execution while the collection is being cleared, expose a method that clears the collection, have clients call that, and don't expose your underlying implementation details. (Which is good practice anyway - look up encapsulation.)

how to use lock on a IList

I have a static collections which implements IList interface. This collection is used throughout the application, including adding/removing items.
Due to multithread issue, I wonder what I can do to ensure that the list is modifying one at a time, such as when 1 thread try to add an item, another thread should not do delete item at that time.
I wonder what is difference between lock(this) and lock(privateObject) ? Which one is better in my case?
Thank you.
The lock(this) will lock on the entire instance while lock(privateObject) will only lock that specific instance variable. The second one is the better choice since locking on the entire instance will prevent other threads from being able to do anything with the object.
From MSDN:
In general, avoid locking on a public
type, or instances beyond your code's
control. The common constructs lock
(this), lock (typeof (MyType)), and
lock ("myLock") violate this
guideline:
lock (this) is a problem if the
instance can be accessed publicly.
lock (typeof (MyType)) is a problem if
MyType is publicly accessible.
lock(“myLock”) is a problem since any
other code in the process using the
same string, will share the same lock.
Best practice is to define a private
object to lock on, or a private static
object variable to protect data common
to all instances.
In this particular case, the collection is static which effectively means there is a single instance but that still doesn't change how the lock(this) and lock(privateObject) would behave.
By using lock(this) even in a static collection you are still locking the entire instance. In this case, as soon as thread A acquires a lock for method Foo() all other threads will have to wait to perform any operation on the collection.
Using lock(privateObject) means that as soon as thread A acquires a lock for method Foo() all other threads can perform any other operation except Foo() without waiting. Only when another thread tries to perform method Foo() will it have to wait until thread A has completed its Foo() operation and released the lock.
The lock keyword is a little confusing. The object expression in the lock statement is really just an identification mechanism for creating critical sections. It is not the subject of the lock nor is it in any way guarenteed to be safe for multithreaded operations just because it is referenced by the statement.
So lock(this) is creating a critical section identified by the class containing the currently executing method whereas lock(privateObject) is identified by an object that is (presumably anyway) private to the class. The former is more risky because a caller of your class could inadvertantly define their own critical sections using a lock statement that uses that class instance as the lock object. That could lead to unintended threading problems including, but not limited to, deadlocks and bottlenecks.
You mentioned that you were concerned with multiple threads modifying the collection at the same time. I should point out that you should be equally concerned with threads reading the collection as well even if they are not modifying it. It is likely that you will need some of the same safe guards in place to protect the collection during reads as you would during writes.
Add a private member to the class that methods lock on.
eg.
public class MyClass : IList
{
private object syncRoot = new object();
public void Add(object value)
{
lock(this.syncRoot)
{
// Add code here
}
}
public void Remove(object value)
{
lock(this.syncRoot)
{
// Remove code here
}
}
}
This will ensure that access to the list is syncronized between threads for the adding and removing cases, while maintaining access to the list. This will still let enumerators access the list while another thread can modify it, but that then opens another issue where an enumerator will throw an exception if the collection is modified during the enumeration.

How to make a method exclusive in a multithreaded context?

I have a method which should be executed in an exclusive fashion. Basically, it's a multi threaded application where the method is invoked periodically by a timer, but which could also be manually triggered by a user action.
Let's take an example :
The timer elapses, so the method is
called. The task could take a few
seconds.
Right after, the user clicks on some
button, which should trigger the
same task : BAM. It does nothing
since the method is already running.
I used the following solution :
public void DoRecurentJob()
{
if(!Monitor.TryEnter(this.lockObject))
{
return;
}
try
{
// Do work
}
finally
{
Monitor.Exit(this.lockObject);
}
}
Where lockObject is declared like that:
private readonly object lockObject = new object();
Edit : There will be only one instance of the object which holds this method, so I updated the lock object to be non-static.
Is there a better way to do that ? Or maybe this one is just wrong for any reason ?
This looks reasonable if you are just interested in not having the method run in parallel. There's nothing to stop it from running immediately after each other, say that you pushed the button half a microsecond after the timer executed the Monitor.Exit().
And having the lock object as readonly static also make sense.
You could also use Mutex or Semaphore if you want it to work cross process (with a slight performance penalty), or if you need to set any other number than one of allowed simultaneous threads running your piece of code.
There are other signalling constructs that would work, but your example looks like it does the trick, and in a simple and straightforward manner.
Minor nit: if the lockObject variable is static, then "this.lockObject" shouldn't compile. It also feels slightly odd (and should at least be heavily documented) that although this is an instance method, it has distinctly type-wide behaviour as well. Possibly make it a static method which takes an instance as the parameter?
Does it actually use the instance data? If not, make it static. If it does, you should at least return a boolean to say whether or not you did the work with the instance - I find it hard to imagine a situation where I want some work done with a particular piece of data, but I don't care if that work isn't performed because some similar work was being performed with a different piece of data.
I think it should work, but it does feel a little odd. I'm not generally a fan of using manual locking, just because it's so easy to get wrong - but this does look okay. (You need to consider asynchronous exceptions between the "if" and the "try" but I suspect they won't be a problem - I can't remember the exact guarantees made by the CLR.)
I think Microsoft recommends using the lock statement, instead of using the Monitor class directly. It gives a cleaner layout and ensures the lock is released in all circumstances.
public class MyClass
{
// Used as a lock context
private readonly object myLock = new object();
public void DoSomeWork()
{
lock (myLock)
{
// Critical code section
}
}
}
If your application requires the lock to span all instances of MyClass you can define the lock context as a static field:
private static readonly object myLock = new object();
The code is fine, but would agree with changing the method to be static as it conveys intention better. It feels odd that all instances of a class have a method between them that runs synchronously, yet that method isn't static.
Remember you can always have the static syncronous method to be protected or private, leaving it visible only to the instances of the class.
public class MyClass
{
public void AccessResource()
{
OneAtATime(this);
}
private static void OneAtATime(MyClass instance)
{
if( !Monitor.TryEnter(lockObject) )
// ...
This is a good solution although I'm not really happy with the static lock. Right now you're not waiting for the lock so you won't get into trouble with deadlocks. But making locks too visible can easily get you in to trouble the next time you have to edit this code. Also this isn't a very scalable solution.
I usually try to make all the resources I try to protect from being accessed by multiple threads private instance variables of a class and then have a lock as a private instance variable too. That way you can instantiate multiple objects if you need to scale.
A more declarative way of doing this is using the MethodImplOptions.Synchronized specifier on the method to which you wish to synchronize access:
[MethodImpl(MethodImplOptions.Synchronized)]
public void OneAtATime() { }
However, this method is discouraged for several reasons, most of which can be found here and here. I'm posting this so you won't feel tempted to use it. In Java, synchronized is a keyword, so it may come up when reviewing threading patterns.
We have a similar requirement, with the added requirement that if the long-running process is requested again, it should enqueue to perform another cycle after the current cycle is complete. It's similar to this:
https://codereview.stackexchange.com/questions/16150/singleton-task-running-using-tasks-await-peer-review-challenge
private queued = false;
private running = false;
private object thislock = new object();
void Enqueue() {
queued = true;
while (Dequeue()) {
try {
// do work
} finally {
running = false;
}
}
}
bool Dequeue() {
lock (thislock) {
if (running || !queued) {
return false;
}
else
{
queued = false;
running = true;
return true;
}
}
}

Categories