When a thread tries to enter a critical section and obtain a lock, what is it actually doing?
I'm asking this because I usually create an object (of type object) which will serve for locking purposes only.
Consider the following: I want to write a method which accepts a collection, and an object which will serve as the locking object so the whole collection manipulation inside that method will be declared inside the critical section which will be locked by that given object.
Should I pass that locking object using "ref" or is passing a reference copy of that object is enough? In other words - since the lock statement is used with reference types only, does the mechanism check the value of the referenced object, or does it check the pointer's value? because obviously, when passing an object without "ref", I actually get a copy of the reference, and not the reference itself.
Here's a typical pattern that you can follow for locking. Basically, you can create a locking object that is used to lock access to your critical section (which, as #Hans said, is not protecting the object that you're working on -- it just handles the lock).
class ThreadSafe
{
static readonly object _locker = new object();
static int _val1, _val2;
static void Go()
{
lock (_locker)
{
if (_val2 != 0) Console.WriteLine (_val1 / _val2);
_val2 = 0;
}
}
}
This example was from Joseph Albahari's online book on threading. It provides an excellent overview of what's going on when you create a lock statement and some tips/tricks on how to best optimize for it. Definitely highly recommended reading.
Per Albahari, again, the lock statement translates in .NET 4 as:
bool lockTaken = false;
try
{
Monitor.Enter (_locker, ref lockTaken);
// Do your stuff...
}
finally { if (lockTaken) Monitor.Exit (_locker); }
It's actually safer than a straight Monitor.Enter and then calling Monitor.Exit in your finally, which is why it was added in .NET 4.
It's enough to lock the object without passing ref. What lock actually does is, call
Monitor.Enter on the beginning of the block and Monitor.Exit on exit.
Hope this helps.
MSDN says here about lock
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. 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.
which means it's not about the reference or pointer it is about the actual object which is pointed by the reference so you won't need to pass as ref simple pass by reference will work
Regarding what actually happens inside the lock see answer to this question which says
"The lock statement is translated by C# to the following:"
var temp = obj;
Monitor.Enter(temp);
try
{
// body
}
finally
{
Monitor.Exit(temp);
}
Should I pass that locking object using "ref" or is passing a reference copy of that object is enough?
Probably neither. If you have some resource that is not thread-safe, the best option usually is to access that resource directly only from one class, which has a lock object as a field (or you can lock directly on the resource). If you pass the lock object to others, it's hard to make sure that the code will still work properly, e.g. locking is done when it should and there are no deadlocks.
But if you really want to pass the lock object, you don't need to use ref, as others have pointed out. Locking is done on the instance of the object, not on the variable containing reference to it.
Related
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).
I am reading this stackoverflow post, which give the sample code as :
static void modifySharedResource(SomeClass sc)
{
//do something
lock (_lock)
{
//where sc is modified
}
}
I am curious that, why this static method need a lock, does the static method thread-safe in this sample ?
I also read this post, but I didn't understand the answer.
Could anyone give more detailed information about my question, thanks !
Whether a method is thread safe or not depends on whether or not it accesses shared resources (e.x static variables,..). There is nothing to do with whether the method is static.
In your case, it's not sure to tell whether modifying sc is thread safe or not. It depends on how this parameter is created and passed in to the method. In most of the cases, it's problematic if the passed in parameter is shared. When we develop a function, we should ensure that there is no problem no matter how the function is used.
With your lock (I assume that _lock is a static variable), you still don't achieve thread safe if sc is shared and modified somewhere else on another thread.
With the method named modifySharedResource (the parameter is shared), I'm quite sure there is a problem if the parameter is also modified somewhere else on another thread.
In general, it's a bad practice to modify incoming parameters: https://softwareengineering.stackexchange.com/questions/245767/is-it-an-antipattern-modifying-an-incoming-parameter
you have a misunderstanding with thread-safe, keyword lock marks bit in sync block index of own parameter (_lock in your code) and another lock can't pass until other lock release _lock and revert bit
The issue here is that the SomeClass is not thread safe. The static method as you have it here is thread safe.
To mark code as a critical section we do this:
Object lockThis = new Object();
lock (lockThis)
{
//Critical Section
}
Why is it necessary to have an object as a part of the lock syntax? In other words, why can't this work the same:
lock
{
//Critical Section
}
Because you don't just lock - you lock something (you lock a lock).
The point of locking is to disallow two threads from directly competing for the same resource. Therefore, you hide that resource behind an arbitrary object. That arbitrary object acts as a lock. When one thread enters a critical section, it locks the lock and the others can't get in. When the thread finishes its work in the critical section, it unlocks and leaves the keys out for whichever thread happens to come next.
If a program has one resource that's candidate for competing accesses, it's possible that it will have other such resources as well! But often these resources are independent from each other - in other words, it may make sense for one thread to be able to lock one particular resource and another thread in the meantime to be able to lock another resource, without those two interfering.
A resource may also need to be accessed from two critical sections. Those two will need to have the same lock. If each had their own, they wouldn't be effective in keeping the resource uncontested.
Obviously, then, we don't just lock - we lock each particular resource's own lock. But the compiler can't autogenerate that arbitrary lock object silently, because it doesn't know which resources should be locked using the same lock and which ones should have their own lock. That's why you have to explicitly state which lock protects which block (or blocks) of code.
Note that the correct usage of an object as a lock requires that the object is persistent (at least as persistent as the corresponding resource). In other words, you can't create it in a local scope, store it in a local variable and throw it away when the scope exits, because this means you're not actually locking anything. If you have one persistent object acting as a lock for a given resource, only one thread can enter that section. If you create a new lock object every time someone attempts to get in, then anyone can enter at all times.
It needs something to use as the lock.
This way two different methods can share the same lock, so only one can be used at a time.
Object lockThis = new Object();
void read()
{
lock (lockThis)
{
//Critical Section
}
}
void write()
{
lock (lockThis)
{
//Critical Section
}
}
Well the simple answer is that that's just how the language is specified. Locks need to have some sort of object to lock on. This allows you to control what code must be locked by controlling the scope and lifecycle of this object. See lock Statement (C# Reference).
It's possible that the designers of the language could have provided an anonymous-style lock like you've suggested, and rely on the compiler to generate an appropriate object behind the scenes. But should the object that's created be a static or instance member? How would it be used if you had multiple methods that need a lock in one class? These are difficult questions, and I'm sure the designers of the language simply didn't feel the benefit of including such a construct would be worth the added complexity or confusion it would entail.
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.
I need to implement the class that should perform locking mechanism in our framework.
We have several threads and they are numbered 0,1,2,3.... We have a static class called ResourceHandler, that should lock these threads on given objects. The requirement is that n Lock() invokes should be realeased by m Release() invokes, where n = [0..] and m = [0..]. So no matter how many locks was performed on single object, only one Release() call is enough to unlock all. Even further if o object is not locked, Release() call should perform nothing. Also we need to know what objects are locked on what threads.
I have this implementation:
public class ResourceHandler
{
private readonly Dictionary<int, List<object>> _locks = new Dictionary<int, List<object>>();
public static ResourceHandler Instance {/* Singleton */}
public virtual void Lock(int threadNumber, object obj)
{
Monitor.Enter(obj);
if (!_locks.ContainsKey(threadNumber)) {_locks.Add(new List<object>());}
_locks[threadNumber].Add(obj);
}
public virtual void Release(int threadNumber, object obj)
{
// Check whether we have threadN in _lock and skip if not
var count = _locks[threadNumber].Count(x => x == obj);
_locks[threadNumber].RemoveAll(x => x == obj);
for (int i=0; i<count; i++)
{
Monitor.Exit(obj);
}
}
// .....
}
Actually what I am worried here about is thread-safety. I'm actually not sure, is it thread-safe or not, and it's a real pain to fix that. Am I doing the task correctly and how can I ensure that this is thread-safe?
Your Lock method locks on the target objects but the _locks dictionary can be accessed by any thread at any time. You may want to add a private lock object for accessing the dictionary (in both the Lock and Release methods).
Also keep in mind that by using such a ResourceHandler it is the responsibility of the rest of the code (the consuming threads) to release all used objects (a regular lock () block for instance covers that problem since whenever you leave the lock's scope, the object is released).
You also may want to use ReferenceEquals when counting the number of times an object is locked instead of ==.
You can ensure this class is thread safe by using a ConcurrentDictionary but, it won't help you with all the problems you will get from trying to develop your own locking mechanism.
There are a number locking mechansims that are already part of the .Net Framework, you should use those.
It sounds like you are going to need to use a combination of these, including Wait Handles to achieve what you want.
EDIT
After reading more carefully, I think you might need an EventWaitHandle
What you have got conceptually looks dangerous; this is bacause calls to Monitor.Enter and Monitor.Exit for them to work as a Lock statement, are reccomended to be encapsulated in a try/finally block, that is to ensure they are executed sequetally. Calling Monitor.Exit before Monitor.Enter will throw an exception.
To avoid these problems (if an exception is thrown, the lock for a given thread may-or-may-not be taken, and if a lock is taken it will not be released, resulting in a leaked lock. I would recomend using one of the options provided in the other answers above. However, if you do want to progress with this mechanism, CLR 4.0 added the following overload to the Monitor.Enter method
public static void Enter (object, ref bool lockTaken);
lockTaken is false if and only if the Enter method throws an exception and the lock was not taken. So, using your two methods using a global bool lockTaken you can create something like (here the example is for a single locker - you will need a Dictionary of List<bool> corresponding to your threads - or event better a Tuple). So in your method Lock you would have something like
bool lockTaken = false;
Monitor.Enter(locker, ref lockTaken);
in the other method Release
if (lockTaken)
Monitor.Exit(locker);
I hope this helps.
Edit: I don't think I fully appreciate your problem, but from what I can gather I would be using a Concurrent Collection. These are fully thead safe. Check out IProducerConsumerCollection<T> and ConcurrentBag<T>. These should facilitate what you want with all thread safter taken care of by the framework (note. a thread safe collection doesn't mean the code it executes is thread safe!). However, using a collection like this, is likely to be far slower than using locks.
IMO you need to use atomic set of functions to make it safe.
http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx
Mutexes I guess will help u.