c# lock question: lock(this) vs lock(SyncRoot) - c#

I have a class with a field of type collection.
Questions:
if I lock(this), do I effectively lock the collection too?
what is more efficient, to do lock(this) or to create a SyncRoot object and do lock(SyncRoot)?

Don't lock on this. It could be the case that someone else has used the instance as a lock object too. Use specifically designated lock objects.
1) if I lock(this), do I effectively lock the collection too?
No.
2) what is more efficient, to do lock(this) or to create a SyncRoot object and do lock(SyncRoot) ?
Efficient? Focus on semantics. locking on this is dangerous. Don't do it. The difference in performance, if any, is not material.
Seriously, it's akin to asking, what will get me to my destination faster, driving 100 MPH the wrong way down the freeway, or walking?

Always use lock(_syncRoot).
Where _syncRoot is a private field (just has to be an object).
This is no difference in terms of efficiency, but you're better to have a private field that you're in control of to lock on. If you lock on this, another object may also be locking on it.
See Why is lock(this) {...} bad? for a much better explanation. Also have a look at the msdn article on lock.
By locking on a collection, you aren't doing anything to stop it from being changed. A misunderstanding you might have, is that lock doesn't do anything special to stop that object being changed, it only works if every critical piece of code also calls lock.

When using lock you aren't doing anything magical to the object you put inside the lock - it isn't making it read only or anything like that. It is just making a note that something has a lock reference to that object. So if anybody else tries to get a lock on that object at the same time it will do what you expect (prevent synchronous access).
What lock doesn't do is care about any properties, fields or anything else in the object you are locking. So no, you aren't locking the collection at all.
This is explained at greater length in this question: Why is lock(this) {...} bad? (which I got from other answers but is an excellent answerand I felt it should be included here too).
As for efficiency I wouldn't expect there to be a lot of performance difference between the two. However as others have said you should not lock on something that might be locked by something outside of your control. This is why more often than not you will find private variables being created for this.
Personally I'd give it a more descriptive name than synclock to describe exactly what the locking process is for (eg saveLock).

A lot of people are saying that lock(this) is dangerous. However The MSDN description of ICollection.SyncRoot states:
For collections whose underlying store is not publicly available, the expected implementation is to return the current instance
If a class follows this guideline, then yes, lock(this) is effectively the same as lock(SyncRoot). But you shouldn't rely on implementation details like this, and should use the more explicit lock(SyncRoot).
Of course, if you don't want to publicly expose locking semantics, but use lock within your class implementation, then you should lock on a private object as others have recommended, and as MSDN recommends. But that doesn't seem to be what you're asking.
Both locking on an instance (lock(this)) and locking on a public property (lock(SyncRoot)) expose you to having the lock taken by code you don't control. If your intention is to expose locking semantics to callers, you have no choice but to do this.

Always lock on something over which the locking code has control. You have no control over a type or an instance of a type.

Related

Locking on the object that is being synchronized or using a dedicated lock object? [duplicate]

This question already has answers here:
C# lock statement, what object to lock on?
(4 answers)
Closed 6 years ago.
As far as I've understood from colleagues and the web, it is bad practice to lock on the object that is being synchronized, but what I dont understand is why?
The following class is supposed to load settings to a dictionary, and it has a method to retrieve settings as well.
public class TingbogSettingService : ITingbogSettingService
{
private readonly ISettingRepository _settingRepository;
private readonly ICentralLog _centralLog;
private Dictionary<string, ISetting> _settingDictionary = new Dictionary<string, ISetting>();
public TingbogSettingService(ISettingRepository settingRepository, ICentralLog centralLog)
{
_settingRepository = settingRepository;
_centralLog = centralLog;
}
public ISetting GetSetting(string settingName)
{
ISetting setting;
if (!_settingDictionary.TryGetValue(settingName, out setting))
{
return null;
}
return setting;
}
public void LoadSettings()
{
var settings = _settingRepository.LoadSettings();
try
{
lock (_settingDictionary)
{
_settingDictionary = settings.ToDictionary(x => x.SettingName);
}
}
catch (Exception ex)
{
_centralLog.Log(Targets.Database, LogType.Error, $"LoadSettings error: Could not load the settings", new List<Exception>() { ex });
}
}
}
During the LoadSettings function I want to lock the _settingDictionary, so that GetSetting will be blocked, until the new settings are loaded.
Should I use a dedicated lock object instead?
For instance:
private static readonly object m_Lock = new object();
…
lock (m_Lock)
EDIT
I thought that lock(_settingDictionary) would lock the _settingDictionary itself, however I now realize that his is not the case. What I wanted was to prevent other threads from accessing _settingDictionary until the new settings were loaded (LoadSettings method completed). As only 1 thread is updating the _settingDictionary, I guess I dont need a lock there at all.
As for closing the question - something similar has been asked before, yes, but the scenario is not the same. I learned from your answers and it is going to be hard to pick a winner amongst y'all.
This is quite a broad subject, but let me focus on one major problem in your code: _settingDictionary changes.
You don't lock on the field, you lock on the instance. This means that when you lock on _settingDictionary, and then you change _settingDictionary, you're not preventing any concurrent access - anyone can lock on the new _settingDictionary.
lock doesn't prevent access to the object you're locking either. If you need synchronization, you must synchronize all access to the object, including your _settingDictionary.TryGetValue. Dictionary isn't thread-safe.
The main guide-lines to what you should lock on are something like this:
The lock object is private to the locker - if it's not private, some other class might be holding a lock on your object, which may lead to deadlocks.
The field should be readonly - this is not a strict requirement, but it makes things easier. The main point is that you must not lock on an object that might change while the lock is being held; others trying to take the lock concurrently will succeed.
The lock object is a reference type - this kind of goes without saying, but you cannot lock on e.g. an int field, since it is boxed when you try to lock it - in effect, this is the same as the previous point - everyone locks on their own instance of the object, eliminating all synchronization.
Obligatory disclaimer: Multi-threading is hard. Seriously hard. Make sure you understand what's happening and what can possibly happen. Any multi-threaded code you write must be written in a way that's correct, first and foremost. http://www.albahari.com/threading/ is a great starter on all things multi-threaded in C#/.NET.
There is no "right" or "wrong" answer to this but there are some guidelines and some things to be aware of.
First, there's many that feel that Microsoft should never have allowed to lock on arbitrary objects. Instead they should've encapsulated the locking functionality into a specific class and avoided potential overhead in every other object out there.
The biggest problem with allowing locking on arbitrary objects is that if you lock on an object you make publicly available to 3rd party code, you have no control over who else might be locking on the same object. You could write your code to the letter, dotting every I and it would still end up deadlocking because some other, 3rd party, code is locking on the same object out of your control.
So that point alone is guideline enough to say "don't ever lock on objects you make publicly available".
But what if the object you want to synchronize access to is private? Well, then it becomes more fuzzy. Presumably you have full control over the code you write yourself and thus if you then lock on the dictionary, as an example, then it will work just fine.
Still, my advice would be to always set up a separate object to lock on, get into this habit, and then you won't so easily make mistakes if you later decides to expose a previously private object into the public and forgetting to separate the locking semantics from it.
The simplest locking object is just that, an object:
private readonly object _SomethingSomethingLock = new object();
Also know, though I think you already do, that locking on an object does not "lock the object". Any other piece of code that doesn't bother with locks can still access the object just fine.
Here is also something I just noticed about your code.
When you do this:
lock (x)
You don't lock on x, you lock on the object that x refers to at the time of the lock.
This is important when looking at this code:
lock (_settingDictionary)
{
_settingDictionary = settings.ToDictionary(x => x.SettingName);
}
Here you have two objects in play:
The dictionary that settingDictionary refers to at the time of lock (_settingDictionary)
The new dictionary that .ToDictionary(...) returns
You have a lock on the first object, but not on the second. This is another scenario where having a dedicated locking object would not only make sense, but also be correct, as the above code is buggy in my opinion.
The problem you are talking about happens when you lock on an object to which external users of your class have access - most commonly, the object itself, i.e. lock (this).
If your code were locking on this instead of _settingDictionary, someone else could deadlock your code as follows:
TingbogSettingService svc = ...
lock (svc) {
Task.Run(() => {
svc.LoadSettings();
});
}
When you lock on a private object, such as _settingDictionary in your case, there harmful effect described above is avoided, because nobody outside your code can lock on the same object.
Note: Using the lock in your code does not make it thread-safe, because GetSetting method does not lock on _settingDictionary when reading from it. Moreover, the fact that you re-assing _settingDictionary inside the lock makes locking irrelevant, because after the reassignment another thread can enter protected section in the lock.
There are different thing you could lock:
a dedicated non static object: private readonly object m_Lock = new object();
a dedicated static object (your example): private static readonly object m_Lock = new object();
the object itself: lock (_settingDictionary)
this, typeof(MyClass)...
The first two are OK but actually different. Locking on a static object means the lock is shared between all instances of your classes. Locking on a non-static object means the lock is different for each instance of your class.
The third option is OK, it's the same as the first one. The only difference is that the object is not read-only (using a read-only field is slightly better as you ensure it won't ever change).
The last option is a bad option for various reasons, see Why is lock(this) {...} bad?
So be careful about what you lock, your example uses a static object while your initial code uses a non-static object. Those are really different use cases.
It is better to use a dedicated object that is not modified by the block of code or used for other purposes in some other methods. That way the object has a single responsibility so that you don't mix the usage of it as a synchronization object, with it being maybe set to null at some point or reinitialized by another method.
lock (_settingDictionary) doesn't lock the dictionary specified between (), it locks the next block of code by using _settingDictionary as a synchronization object (To know if the block has been entered of left by another thread by setting some flags on that object).

Why is specifying a synchronization object in the lock statement mandatory

I'm trying to wrap my mind around what exactly happens in the lock statement.
If I understood correctly, the lock statement is syntactic sugar and the following...
Object _lock = new Object();
lock (_lock)
{
// Critical code section
}
...gets translated into something roughly like:
Object _lock = new Object();
Monitor.Enter(_lock);
try
{
// Critical code section
}
finally { Monitor.Exit (_lock); }
I have used the lock statement a few times, and always created a private field _lock, as a dedicated synchronization object. I do understand why you should not lock on public variables or types.
But why does the compiler not create that instance field as well? I feel there might in fact be situations where the developer wants to specify what to lock on, but from my experience, in most cases that is of absolutely no interest, you just want that lock! So why is there no parameterless overload of lock?
lock()
{
// First critical code section
}
lock()
{
// Second critical code section
}
would be translated into (or similar):
[DebuggerHidden]
private readonly object _lock1 = new object()
[DebuggerHidden]
private readonly object _lock2 = new object()
Monitor.Enter(_lock1);
try
{
// First critical code section
}
finally { Monitor.Exit(_lock1); }
Monitor.Enter(_lock2);
try
{
// Second critical code section
}
finally { Monitor.Exit(_lock2); }
EDIT: I have obviously been unclear concerning multiple lock statements. Updated the question to contain two lock statements.
The state of the lock needs to be stored. Whether or not it was entered. So that another thread that tries to enter the same lock can be blocked.
That requires a variable. Just a very simple one, an plain object is enough.
A hard requirement for such a variable is that it is created before any lock statement uses it. Trying to create it on-the-fly as you propose creates a new problem, there's a now a need to use a lock to safely create the variable so that only the first thread that enters the lock creates it and other threads trying to enter the lock are blocked until it is created. Which requires a variable. Etcetera, an unsolvable chicken-and-egg problem.
There can be situations when you will need two different lock's, which are independent of each other. Meaning when one 'lockable' part of code is locked other 'lockable' should not be locked. That's why there is ability to provide lock objects - you can have several of them for several independent lock's
In order for the no-variable thing to work, you'd have to either:
Have one auto-generated lock variable per lock block (what you did, which means that you can't have two different lock blocks locking on the same variable)
Use the same lock variable for all lock blocks in the same class (which means you can't have two independent things protected)
Plus, you'd also have the issue of deciding whether those should be instance-level or static.
In the end, I'm guessing the language designers didn't feel that the simplification in one specific case was worth the ambiguity introduced while reading code. Threading code (which is the reason to use locks) is already hard to write correctly and verify. Making it harder would be a not-good thing.
Allowing for an implicit lock object might encourage the use of a single lock object, which is considered bad practice. By enforcing the use of an explicit lock object, the language encourages you to name the lock something useful, such as "countIncementLock".
A variable named thusly would not encourage developers to use the same lock object when performing a completely separate operation, such as writing to a stream of some kind.
Therefore, the object could be writing to a stream on one thread, while incrementing a counter on another thread, and neither of the threads would necessarily interfere with each other.
The only reason why the language wouldn't do this is because is because it would look like a good practice, but in reality would be hiding a bad practice.
Edit:
Perhaps the designers of C# did not want implicit lock variables because they thought it might encourage bad behavour.
Perhaps the designers did not think of implicit lock variables at all, because they had other more important things to think about first.
If every C# developer knew exactly what was happening when they wrote lock(), and they knew the implications, then there's no reason why it shouldn't exist, and no reason why it shouldn't work how you're suggesting.

Is using an existing object rather than creating a specific lock object safe?

EDIT: As it turns out when I was browsing I found a question the appears to be the same as mine which I didn't find earlier: Difference between lock(locker) and lock(variable_which_I_am_using)
I am looking at some code and trying to get my head around the locking thing and I am getting there I think.
Now I noticed in some code I am reviewing that an object is created like so:
private HashSet<Graphic> clustersInUse = new HashSet<Graphic>();
Then further in the code is used like so:
lock (clustersInUse)
{
// Do something with the Hashset
}
Now, is there a problem doing this rather than creating a specific object for the lock. Like this:
private object clusterLocker = new object();
What happens if the clustersInUse above somehow gets put into a public property, what happens then?
Also, if something tries to access the clustersInUse without locking it whilst it is locked in another thread what would happen then?
The general rule is that you want to control the scope of the object your locking on to prevent some unknown code from causing unexpected behavior. In this case you are using a private instance variable so you are probably OK as long as you are not handing out references to it.
If you are handing out references and locking on it and other code is locking those references (e.g. when modifying the collection) changing the behavior could easily introduce threading bugs.
If someone puts it into a public property that counts as "handing out references" if they lock on it your call to lock will block until they unlock it. Whether this is desirable or not depends on what they are doing with the collection.
Having the object locked will have have no effect on using the object for any purpose other than synchronization.
You've pretty much answered your own question. For locking, it's generally better to create an object specifically for the purpose, and usually held privately for use by accessor methods that express synchronisation logic at a high level.

Safe to get Count value from generic collection without locking the collection?

I have two threads, a producer thread that places objects into a generic List collection and a consumer thread that pulls those objects out of the same generic List. I've got the reads and writes to the collection properly synchronized using the lock keyword, and everything is working fine.
What I want to know is if it is ok to access the Count property without first locking the collection.
JaredPar refers to the Count property in his blog as a decision procedure that can lead to race conditions, like this:
if (list.Count > 0)
{
return list[0];
}
If the list has one item and that item is removed after the Count property is accessed but before the indexer, an exception will occur. I get that.
But would it be ok to use the Count property to, say, determine the initial size a completely different collection? The MSDN documentation says that instance members are not guaranteed to be thread safe, so should I just lock the collection before accessing the Count property?
I suspect it's "safe" in terms of "it's not going to cause anything to go catastrophically wrong" - but that you may get stale data. That's because I suspect it's just held in a simple variable, and that that's likely to be the case in the future. That's not the same as a guarantee though.
Personally I'd keep it simple: if you're accessing shared mutable data, only do so in a lock (using the same lock for the same data). Lock-free programming is all very well if you've got appropriate isolation in place (so you know you've got appropriate memory barriers, and you know that you'll never be modifying it in one thread while you're reading from it in another) but it sounds like that isn't the case here.
The good news is that acquiring an uncontested lock is incredibly cheap - so I'd go for the safe route if I were you. Threading is hard enough without introducing race conditions which are likely to give no significant performance benefit but at the cost of rare and unreproducible bugs.

What is a best approach to make a function or set of statements thread safe in C#?

What is a best approach to make a function or set of statements thread safe in C#?
Don't use shared read/write state when possible. Go with immutable types.
Take a look at the C# lock statement. Read Jon Skeet's article on multi threading in .net.
It depends on what you're trying to accomplish.
If you want to make sure that in any given time only one thread would run a specific code use lock or Monitor:
public void Func(...)
{
lock(syncObject)
{
// only one thread can enter this code
}
}
On the other hand you want multiple threads to run the same code but do not want them to cause race conditions by changing the same point in memory don't write to static/shared objects which can be reached by multiple at the same time.
BTW - If you want to create a static object that would be shared only within a single thread use the ThreadStatic attribute (http://msdn.microsoft.com/en-us/library/system.threadstaticattribute(VS.71).aspx).
Use lock statement around shared state variables. Once you ensured thread safety, run code through code profiler to find bottlenecks and optimize those places with more advanced multi-threading constructs.
The best approach will vary depending on your exact problem at hand.
The simplest approach in C# is to "lock" resources shared by multiple threads using a lock statement. This creates a block of code which can only be accessed by one thread at a time: the one which has obtained the "lock" object. For example, this property is thread safe using the lock syntax:
public class MyClass
{
private int _myValue;
public int MyProperty
{
get
{
lock(this)
{
return _myValue;
}
}
set
{
lock(this)
{
_myValue = value;
}
}
}
}
A thread aquires the lock at the start of the block and only releases the lock at the end of the block. If the lock is not available, the thread will wait until the lock is available. Obviously, access to the private variable within the class is not thread-safe, so all threads must access the value through the property to be safe.
This is by far the simplest way for threads to have safe access to shared data, however it only touches the tip of the iceberg of techniques for threading.
Write the function in such a way that:
It does not modify its parameters in any way
It does not access any state outside of its local variables.
Otherwise, race conditions MAY occur. The code must be thoroughly examined for such conditions and appropriate thread synchronization must be implemented (locks, etc...). Writing code that does not require synchronization is the best way to make it thread-safe. Of course, this is often not possible - but should be the first option considered in most situations.
There's a lot to understand when learning what "thread safe" means and all the issues that are introduced (synchronization, etc).
I'd recommend reading through this page in order to get a better feel for what you're asking: Threading in C#. It gives a pretty comprehensive overview of the subject, which sounds like it could be pretty helpful.
And Mehrdad's absolutely right -- go with immutable types if you can help it.

Categories

Resources