Did I do locks all the time?

I read this article on thread safety in singleton, and it seemed to me that I did not understand the lock method.

In the second version, the author has the following:

 public sealed class Singleton { private static Singleton instance = null; private static readonly object padlock = new object(); Singleton() { } public static Singleton Instance { get { lock (padlock) { if (instance == null) { instance = new Singleton(); } return instance; } } } } 

While I would do something like this:

 public sealed class Singleton { private static Singleton instance = null; Singleton() { } public static Singleton Instance { get { lock (instance) { if (instance == null) { instance = new Singleton(); } return instance; } } } } 

Why are you using a padlock object and not blocking the actual object you want to lock?

+4
source share
3 answers

What do you expect to see when you first access the Instance property before you have an object to block?

(Hint: lock(null) comes in ...)

As a standalone measure, I almost always avoid locking on the “actual object” - because there can usually be other code referenced by this link, and I don’t necessarily know that it will block. Even if your version really works, what will happen if some external code wrote:

 // Make sure only one thread is ever in this code... lock (Singleton.Instance) { // Do stuff } 

Now no one can even get an instance while this code is running, because they will be locked in the getter. A getter lock is not designed to protect against this — it is only intended to protect against multiple access at the receiver.

The tighter you can control your locks, the easier it is for them to reason and avoid deadlocks.

I very rarely have to block a "normal" object if:

  • I do not show this link outside this class
  • I am sure that the type itself (which will always refer to this , of course) will not block itself.

(All this is an excuse to avoid blocking on this too, of course ...)

Basically, I believe that the idea of ​​allowing you to block any object was a bad idea in Java, and it was nice to copy it to .NET :(

+13
source

Locking on this or any other non-closed object is dangerous because it can lead to deadlocks if someone else tries to use this object for synchronization.

This is not terribly likely, so people can get used to doing this for years without even biting. But this is still possible, and the cost of a private instance of object is probably not large enough to justify the risk.

+2
source

You can use any type of object to block, the type really does not matter, it is just used as a flag, and only one thread can hold it at a time.

Of course, this is possible as a blocking parameter. But I believe that the main reason why this is not recommended is that another class somewhere can also use an instance of your class as a lock object and which can cause problems with defects.

+1
source

Source: https://habr.com/ru/post/1398115/


All Articles