multithreading: lock on property - is this correct? - c#

I have written the following code:
static readonly object failedTestLock = new object();
public static Dictionary<string, Exception> FailedTests
{
get
{
lock (failedTestLock)
{
return _failedTests;
}
}
set
{
lock (failedTestLock)
{
_failedTests = value;
}
}
}
public void RunTest(string testName)
{
try
{
//Run a test
}
catch (Exception exception)
{
// ?? Is this correct / threadsafe?
FailedTests.Add(testName, exception);
}
}
QUESTION:
Is this a correct manner to safely add the failed test to the Dictionary?
Is this threadsafe?
Is FailedTests.Add called INSIDE the lock or OUTSIDE the lock?
Can you explain why this is correct/threadsafe or why not?
Thanks in advance

The fundamental problem with the code above is that it only locks access to _failedTests when a thread is getting the dictionary or setting it. Only one thread can get a reference to the dictionary at a time, but once a thread has a reference to the dictionary, it can read and manipulate it without being constrained by locks.
Is this a correct manner to safely add
the failed test to the Dictionary?
No, not if two threads are trying to add to the dictionary at the same time. Nor if you expect reads and writes to happen in a particular order.
Is this threadsafe?
It depends what you mean by threadsafe, but no, not by any reasonable definition.
Is FailedTests.Add called INSIDE the
lock or OUTSIDE the lock?
The dictionary retrieval (the get accessor) happens inside a lock. This code calls Add after releasing the lock.
Can you explain why this is correct/threadsafe or why not?
If multiple threads operate on your dictionary at the same time, you can't predict the order in which those threads will change its contents and you can't control when reads will occur.

This is not thread-safe access to a dictionary, because only the property access that returns the dictionary object is thread-safe, but you are not synchronizing the call to the Add method. Consider using ConcurrentDictionary<string,Exception> in this case, or synchronize calls to Add manually.

I don;t thinks this is threadsafe, because the lock is kept only in the very brief moment where the pointer to the collection is returned. When you Add to the collection there is no lock so if two threads try to add at the same time you'll get a nasty error.
So you should lock around the FailedTest.Add code.
You may also want to look into concurrent collections, they might provide what you need.
Regards GJ

The call to Add() is outside the locks.
You can solve it by writing your own Add() method to replace the property.

Related

C# Is this method thread safe?

Consider the following code:
Dictionary<string, string> list = new Dictionary<string, string>();
object lockObj = new object();
public void MyMethod(string a) {
if (list.Contains(a))
return;
lock (lockObj) {
list.Add(a,"someothervalue");
}
}
Assuming I'm calling MyMethod("mystring") from different threads concurrently.
Would it be possible for more than one thread (we'll just take it as two) enter the if (!list.Contains(a)) statement in the same time (with a few CPU cycles differences), both threads get evaluated as false and one thread enters the critical region while another gets locked outside, so the second thread enters and add "mystring" to the list again after the first thread exits, resulting in the dictionary trying to add a duplicate key?
No, it's not thread-safe. You need the lock around the list.Contains too as it is possible for a thread to be switched out and back in again between the the if test and adding the data. Another thread may have added data in the meantime.
You need to lock the entire operation (check and add) or multiple threads may attempt to add the same value.
I would recommend using the ConcurrentDictionary(TKey, TValue) since it is designed to be thread safe.
private readonly ConcurrentDictionary<string, string> _items
= new ConcurrentDictionary<string, string>();
public void MyMethod(string item, string value)
{
_items.AddOrUpdate(item, value, (i, v) => value);
}
You need to lock around the whole statement. It's possible for you to run into issues on the .Contains portion (the way your code is now)
You should check the list after locking. e.g.
if (list.Contains(a))
return;
lock (lockObj) {
if (list.Contains(a))
return;
list.Add(a);
}
}
private Dictionary<string, string> list = new Dictionary<string, string>();
public void MyMethod(string a) {
lock (list) {
if (list.Contains(a))
return;
list.Add(a,"someothervalue");
}
}
Check out this guide to locking, it's good
A few guidelines to bear in mind
Generally lock around a private static object when locking on multiple writeable values
Do not lock on things with scope outside the class or local method such as lock(this), which could lead to deadlocks!
You may lock on the object being changed if it is the only concurrently accessed object
Ensure the object you lock is not null!
You can only lock on reference types
I am going to assume that you meant write ContainsKey instead of Contains. Contains on a Dictionary is explicitly implemented so it is not accessible via the type you declared.1
Your code is not safe. The reason is because there is nothing preventing ContainsKey and Add from executing at the same time. There are actually some quite remarkable failure scenarios that this would introduce. Because I looked at how the Dictionary is implemented I can see that your code could cause a situation where data structure contains duplicates. And I mean it literally contains duplicates. The exception will not necessarily be thrown. The other failure scenarios just keep getting stranger and stranger, but I will not go into those here.
One trivial modification to your code might involve a variation of the double-checked locking pattern.
public void MyMethod(string a)
{
if (!dictionary.ContainsKey(a))
{
lock (dictionary)
{
if (!dictionary.ContainsKey(a))
{
dictionary.Add(a, "someothervalue");
}
}
}
}
This, of course, is not any safer for the reason I already stated. Actually, the double-checked locking pattern is notoriously difficult to get right in all but the simplest cases (like the canonical implementation of a singleton). There are many variations on this theme. You can try it with TryGetValue or the default indexer, but ultimately all of these variations are just dead wrong.
So how could this be done correctly without taking a lock? You could try ConcurrentDictionary. It has the method GetOrAdd which is really useful in these scenarios. Your code would look like this.
public void MyMethod(string a)
{
// The variable 'dictionary' is a ConcurrentDictionary.
dictionary.GetOrAdd(a, "someothervalue");
}
That is all there is to it. The GetOrAdd function will check to see if the item exists. If it does not then it will be added. Otherwise, it will leave the data structure alone. This is all done in a thread-safe manner. In most cases the ConcurrentDictionary does this without waiting on a lock.2
1By the way, your variable name is obnoxious too. If it were not for Servy's comment I may have missed the fact that we were talking about a Dictionary as opposed to a List. In fact, based on the Contains call I first thought we were talking about a List.
2On the ConcurrentDictionary readers are completely lock free. However, writers always take a lock (adds and updates that is; the remove operation is still lock free). This includes the GetOrAdd function. The difference is that the data structure maintains several possible lock options so in most cases there is little or no lock contention. That is why this data structure is said to be "low lock" or "concurrent" as opposed to "lock free".
You can first do a non-locking check, but if you want to be thread-safe you need to repeat the check again within the lock. This way you don't lock unless you have to and ensure thread safety.
Dictionary<string, string> list = new Dictionary<string, string>();
object lockObj = new object();
public void MyMethod(string a) {
if (list.Contains(a))
return;
lock (lockObj) {
if (!list.Contains(a)){
list.Add(a,"someothervalue");
}
}
}

Locking function body with function parameter object

Today I came across this piece of code
internal object UpdatePracownik(object employee)
{
lock (employee)
{
// rest of the code
}
return employee;
}
I was wondering if this is valid solution for locking access to function?
Wouldn't be better to use attribute
[MethodImpl(MethodImplOptions.Synchronized)]
instead of this kind of lock ?
Well it depends. If all threads call this method by passing the same globally visible object as parameter then they will all see the same lock and there will be no problems.
If instead each thread will call this method by passing its own object then locking is useless because they all see different locks. We must know the context in which the method is called to see if this is safe or not.
Using the synchronization method proposed by you makes the entire method body be wrapped in a lock(this) statement like:
internal object UpdatePracownik(object employee)
{
lock (this)
{
// code
}
}
which will guarantee atomicity of execution by multiple threads but may be too coarse-grain for your purposes and is generally not advisable.
Using the MethodImpl attribute to synchronise the method is equivalent to locking on an object that is specific to the method.
This means that only one thread at a time can run the method, but there might not be a need to exclude other threads as long as they don't use the same data.
It also means that the method is synchronised by itself, but you might want to lock other methods too using the same identifier. You might for example want the method DeletePracownik to be synchronised along with UpdatePracownik, so that you can't delete one object while it's being updated.
Locking on the employee instance is a bad idea, as is lock on 'this' both for the same reason: code outside of your control may also lock on those instances and cause deadlocks (blogs.msdn.com/b/bclteam/archive/2004/01/20/60719.aspx). It is preferable to use a private member:
private readonly object _lock = new object();
...
lock (_lock)
{
..
}
Furthermore you should familiarise yourself with ReaderWriterLockSlim. Often you may want to allow concurrent access to certain functions, unless a write operation is in progress:
private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();
public void ReadOp()
{
_rwLock.EnterReadLock(); //only blocks if write lock held
try
{
//do read op
}
finally
{
_rwLock.ExitReadLock();
}
}
public void WriteOp()
{
_rwLock.EnterWriteLock(); //blocks until no read or write locks held
try
{
//do write op
}
finally
{
_rwLock.ExitWriteLock();
}
}

Working with global Dictionary inside threads

Suppose that I have a Dictionary<string, string>. The dictionary is declared as public static in my console program.
If I'm working with threads and I want to do foreach on this Dictionary from one thread but at the same time another thread want to add item to the dictionary. This would cause a bug here because we can't modify our Dictionary while we are running on it with a foreach loop in another thread.
To bypass this problem I created a lock statement on the same static object on each operation on the dictionary.
Is this the best way to bypass this problem? My Dictionary can be very big and I can have many threads that want to foreach on it. As it is currently, things can be very slow.
Try using a ConcurrentDictionary<TKey, TValue>, which is designed for this kind of scenario.
There's a nice tutorial here on how to use it.
The big question is: Do you need the foreach to be a snapshot?
If the answer is "no", then use a ConcurrentDictionary and you will probably be fine. (The one remaining question is whether the nature of your inserts and reads hit the striped locks in a bad way, but if that was the case you'd be finding normal reads and writes to the dictionary even worse).
However, because it's GetEnumerator doesn't provide a snapshot, it will not be enumerating the same start at the beginning as it is at the end. It could miss items, or duplicate items. The question is whether that's a disaster to you or not.
If it would be a disaster if you had duplicates, but not otherwise, then you can filter out duplicates with Distinct() (whether keyed on the keys or both the key and value, as required).
If you really need it to be a hard snapshot, then take the following approach.
Have a ConcurrentDictionary (dict) and a ReaderWriterLockSlim (rwls). On both reads and writes obtain a reader lock (yes even though you're writing):
public static void AddToDict(string key, string value)
{
rwls.EnterReadLock();
try
{
dict[key] = value;
}
finally
{
rwls.ExitReadLock();
}
}
public static bool ReadFromDict(string key, out string value)
{
rwls.EnterReadLock();
try
{
return dict.TryGetValue(key, out value);
}
finally
{
rwls.ExitReadLock();
}
}
Now, when we want to enumerate the dictionary, we acquire the write lock (even though we're reading):
public IEnumerable<KeyValuePair<string, string>> EnumerateDict()
{
rwls.EnterWriteLock();
try
{
return dict.ToList();
}
finally
{
rwls.ExitWriteLock();
}
}
This way we obtain the shared lock for reading and writing, because ConcurrentDictionary deals with the conflicts involved in that for us. We obtain the exclusive lock for enumerating, but just for long enough to obtain a snapshot of the dictionary in a list, which is then used only in that thread and not shared with any other.
With .NET 4 you get a fancy new ConcurrentDictionary. I think there are some .NET 3.5-based implementations floating around.
Yes, you will have a problem updating the global dictionary while an enumeration is running in another thread.
Solutions:
Require all users of the dictionary to acquire a mutex lock before accessing the object, and release the lock afterwards.
Use .NET 4.0's ConcurrentDictionary class.

Can I lock a collection in the get accessor?

I have a lightly used dictionary which is hardly ever going to be read or updated since the individual items raise events and return their results with their event args. In fact the thread is always going to be updated with the same thread. I was thinking about adding a simple lock just to be safe. I was wondering if I can just place the lock in the get accessor. Does this work?
Dictionary<string,Indicator> indicators = new Dictionary<string,Indicator>();
Dictionary<string, Indicator> Indicators
{
get
{
lock (indicators)
{
return indicators;
}
}
}
public void AddIndicator(Indicator i)
{
lock (indicators)
{
indicators.Add(i.Name, i);
}
}
That doesn't do anything particularly useful, no.
In particular, if you have:
x = foo.Indicators["blah"]
then the indexer will be executed without the thread holding the lock... so it's not thread-safe. Think of the above code like this:
Dictionary<string, Indicator> indicators = foo.Indicators;
// By now, your property getter has completed, and the lock has been released...
x = indicators["blah"];
Do you ever need to do anything with the collection other than access it via the indexer? If not, you might want to just replace the property with a method:
public Indicator GetIndicator(string name)
{
lock (indicators)
{
return indicators[name];
}
}
(You may want to use TryGetValue instead, etc - it depends on what you're trying to achieve.)
Personally I'd prefer to use a reference to a privately-owned-and-otherwise-unused lock object rather than locking on the collection reference, but that's a separate matter.
As mentioned elsewhere, ConcurrentDictionary is your friend if you're using .NET 4, but of course it's not available prior to that :(
Other than Jon's input, I'll say don't lock the collection indicators itself anyway, from MSDN:
Use caution when locking on instances,
for example lock(this) in C# or
SyncLock(Me) in Visual Basic. If other
code in your application, external to
the type, takes a lock on the object,
deadlocks could occur.
It is recommended to use a dedicated object instance to lock onto. There are other places where this is covered with more details and reasons why - even here on SO, should you care to search for the information when you have time.
Alternatively, you could use ConcurrentDictionary which handles the thread safety for you.
Short answer: YES.
Why shouldn't that work, but as mention by Jon, it does not lock as intended when using indexes?

unprotected access to member in property get

I have a property
public ObservableCollection<string> Name
{
get
{
return _nameCache;
}
}
_nameCache is updated by multiple threads in other class methods. The updates are guarded by a lock. The question is: should I use the same lock around my return statement? Will not using a lock lead to a race condition?
It depends on what you mean by updated.
If you mean that the reference is modified, i.e. _nameCache = newvalue;, then as Mark has said, yes you should (with the same lock) and, no, you won't get a race condition.
If, however, you mean that items are added and removed to the instance referenced by _nameCache, then you won't need to lock on return (since the reference itself never changes). However, you will have to be careful how you read the collection after retrieving it - ideally you should then use the same lock before calling any of its methods.
Either that, or you can use the event model to be notified of new items etc if all you need to do is to track changes - since the events will be raised on the thread that currently has the lock to the collection.
If this is not suitable (because you're always getting elements via an indexer or whatever), then you could always return a copy of the ObservableCollection through this property - i.e. return new ObservableCollection<string>(_nameCache);. This will make the return value of the property short-lived, but leaves any caller free to enumerate and index without any fears of state corruption from other threads.
Yes, you should. If you don't add a lock there the newest value of _nameCache might not be returned.
public ObservableCollection<string> Name
{
get
{
lock (_yourLockObject)
{
return _nameCache;
}
}
}
Yes you can use the same lock object. I assmume you have a variable declared such as the following for the lock: private object _lock = new object(); If so you can use the _lock object as in the follwoing block of code.
public ObservableCollection<string> Name
{
get
{
lock(_lock)
{
return _nameCache;
}
}
}
If you did not implement the lock in the situation where multiple threads are apptempting to access _nameCache you might receive a value that was not within the context of the current call to this propery. So yes its mandatory to implement syncronization (the lock) if multiple threads are accessing the same class memeber such as the propery you outlined above.
Enjoy!

Categories

Resources