I have a generic dictionary in a multithreaded application; to implement a lock i created a property.
static object myLock=new object();
Dictionary<key,SomeRef> dict=new Dictionary<key,SomeRef>();
public Dictionary<key,SomeRef> MyDict{
get{
lock(myLock){
return dict;
}
}
}
Now if i write CODE#1
MyDict.TryGetValue
or CODE#2
var result=MyDict.Values;
foreach(var item in result){
//read value into some other variable
}
so while i m runnig code 1 or 2 and at the same time if some other thread tries to do some write operation on the dictionary like ..clear dict or add new item. then, will this solution be thread safe (using a property).
if not ..then is there any other ways to do this.
When i say write operation it can be take a reference of the dict through property chek key exoist or not if not create key and assign value. (thus me not using the setter in the property)
No, this will not be threadsafe.
The lock will only lock around getting the reference to your internal (dict) instance of the dictionary. It will not lock when the user tries to add to the dictionary, or read from the dictionary.
If you need to provide threadsafe access, I would recommend keeping the dictionary private, and make your own methods for getting/setting/adding values to/from the dictionary. This way, you can put the locks in place to protect at the granularity you need.
This will look something like this:
public bool TryGetValue(key thekey, out SomeRef result)
{
lock(myLock) { return this.dict.TryGetValue(thekey, out result); }
}
public void Add(key thekey, SomeRef value)
{
lock(myLock) { this.dict.Add(thekey, value) }
}
// etc for each method you need to implement...
The idea here is that your clients use your class directly, and your class handles the synchronization. If you expect them to iterate over the values (such as your foreach statement), you can decide whether to copy the values into a List and return that, or provide an enumerator directly (IEnumerator<SomeRef> GetValues()), etc.
No, this will not be safe, as the only code that's locked is the retrieval code. What you need to do is
lock(MyDict)
{
if(MyDict.TryGetValue()...
}
and
lock(MyDict)
{
foreach(var item in MyDict.Values) ...
}
The basic idea is to enclose your working code within the lock() block.
The implementation is not guaranteed to be thread safe as it is. In order to be thread safe concurrent reads/writes must all be protected by the lock. By handing out a reference to your internal dictionary, you're making it very hard to control who accesses the resource and thus you have no guarantee that the caller will use the same lock.
A good approach is to make sure whatever resources you're trying to synchronize access to is completely encapsulated in your type. That will make it much easier to understand and reason about the thread safety of the type.
Thread Safe Dictionary in .NET with ReaderWriterLockSlim
This is a method that uses ReaderWriterLockSlim and deterministic finalization to hold and release locks.
Related
I already have a initialized and filled Dictionary class i read values as below.
public class MyClass
{
public static Dictionary<string,object> Dictionary { get; set; }
public object Get(string key)
{
return Dictionary[key];
}
public List<object> Get(object type)
{
return Dictionary.Where(d=>d.Value == type);
}
}
As you can see that I have only 2 case that i just read values. If there is no any bad side effect in threaded app about above code so i will prefer to use Dictionary instead of using ConcurrentDictionary because of better performance.
Problems arise when threads are modifying the dictionary.
For example, at the same time, thread a is reading from the dictionary while thread b is changing some values. Thread a will get some changed values in his read.
In your case, you are always reading from the Dictionary so you will have no issues.
In theory this is fine, however this is not thread safe because you leave a public reference to the Dictionary via the property. It just depends on how paranoid you want to be in terms of protecting yourself from potential side effects down the road. Even if you pass a reference to the Dictionary into the constructor of my object and refer to is a private in the wrapping class, you still need to deep copy this parameter so that if the caller later modifies the Dictionary its keys/values are not mutated inside your wrapping class.
So as long as you're careful, your solution will work. You are leaving yourself open to potential thread safety issues however.
Multi-threaded management is for resoling race conditions and conflicts during the changing of the data (updating and writing) but for simple reading, if before you jump into the multi-threading you already done with with dictionary construction, you can avoid manage multi-threaded access.
So, I've been spoiled by ConcurrentDictionary and it's awesome TryGetValue method. However, I'm constrained to using only regular Dictionary because this is in a portable class library targeting phone and other platforms. I'm trying to write a very limited subset of a Dictionary and exposing it in a thread-safe manner.
I basically need something like GetOrAdd from ConcurrentDictionary. Right now, I have this implemented like:
lock (lockdictionary)
{
if (!dictionary.ContainsKey(name))
{
value = new foo();
dictionary[name] = value;
}
value = dictionary[name];
}
Is this basically as good as I can get it? I think locking is only really required if the key doesn't exist and it gets added, however, there is no good "get value if it exists, return null otherwise" method. If I were to leave out the ContainsKey bit, when the key didn't exist I'd get an exception because the key doesn't exist.
Is there anyway I could get this to a more lean version? Or is this just the best a regular dictionary can do?
Locking is required even for reading in the presence of concurrent writers. So yes, this is as good as it gets if you mutate the dictionary.
You can of course always create a copy of the entire dictionary each time something is written. That way readers might see an out-of-date version but they can safely read.
You could try using ReaderWriterLockSlim. For example:
ReaderWriterLockSlim locker = new ReaderWriterLockSlim();
//..
public string GetOrAdd(string name)
{
locker.EnterUpgradeableReadLock();
try
{
if(!dictionary.ContainsKey(name))
{
locker.EnterWriteLock();
try
{
dictionary[name] = new foo();
}
finally
{
locker.ExitWriteLock();
}
}
value = dictionary[name];
}
finally
{
locker.ExitUpgradeableReadLock();
}
return value;
}
Your implementation is just fine. Note, that lock implementation has neglictable performance penalty in case of uncontended access. However, in order to achieve true thread-safety you must use lock with EVERY operation with dictionary - I suggest to write wrapper class, like SynchronizedDictinory to keep sync logic in one place
You can use a double-check pattern, as follows:
if (!dictionary.ContainsKey(name))
{
lock (lockdictionary)
{
if (!dictionary.ContainsKey(name))
{
value = new foo();
dictionary[name] = value;
}
value = dictionary[name];
}
}
This ensures you only lock if you actually need to, but also ensures once you have locked that you still need to add the value. The performance should be better than always locking. But don't take my word for it. Run a test!
This is as good as it gets.
Locking is required because dictionary makes no guarantees that you can update and read in parallel at all. Even single call to get element running at the same time as update on other thread may fail due to changes to internal data strucures.
Note that the behavior is explicitly covered in Thread Safety section of Dictionary
A Dictionary can support multiple readers concurrently, as long as the collection is not modified. Even so, enumerating through a collection is intrinsically not a thread-safe procedure. In the rare case where an enumeration contends with write accesses, the collection must be locked during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization.
I have declared a dictionary of dicionary:
Dictionary<String, Dictionary<String, String>> values;
I have a getter to get a dictionary at a specific index:
public Dictionary<String,String> get(String idx)
{
lock (_lock)
{
return values[moduleName];
}
}
As you can see I am working in a multi-threaded environment.
My question is do I need to return a copy of my dictionary in order to be thread safe like this:
public Dictionary<String,String> get(String idx)
{
lock (_lock)
{
return new Dictionary<string, string>(values[moduleName]);
}
}
If I don't will the class that calls the getter receive a copy (so if I remove this dictionary from my Dictionary<String, Dictionary<String, String>> will it still work)?
Cheers,
Thierry.
Dictionary<> is not Thread-safe, but ConncurrentDictionary<> is.
The class calling the getter receives a reference, which means it will still be there if you remove it from the values-Dictionary as the GC does not clean it as long as you have a reference somewhere, you just can't get it with the getter anymore.
Basicaly that means you have two possibilities when using Dictionary<>:
return a copy: Bad idea, because if you change the config you have two different configurations in your app "alive"
lock the instance: this would make it thread-safe, but then use ConcurrentDictionary<> as it does exactly that for you
If you really need to return the dictionary itself, then you're going to need to either have rules for how the threads lock on it (brittle, what if there's a case that doesn't?), use it in a read-only way (dictionary is thread-safe for read-only, but note that this assumes that the code private to the class isn't writing to it any more either), use a thread-safe dictionary (ConcurrentDictionary uses striped locking, my ThreadSafeDictionary uses lock-free approaches, and there are different scenarios where one beats the other), or make a copy as you suggest.
Alternatively though, if you expose a method to retrieve or set the ultimate string that is found by the two keys, to enumerate the second-level keys found by a key, and so on, then not only can you control the locking done in one place, but it's got other advantages in cleanness of interface and in freeing implementation from interface (e.g. you could move from lock-based to use of a thread-safe dictionary, or the other way around, without affecting the calling code).
If you don't return a copy, the caller will be able to change the dictionary but this is not a thread safety issue.
There is also a thread safety issue because you don't expose any lock to synchronize writes and reads. For instance, your writer thread can adds/removes a value while the reader thread is working on the same instance.
Yes, you have to return a copy.
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.)
I have a class that maintains a static dictionary of cached lookup results from my domain controller - users' given names and e-mails.
My code looks something like:
private static Dictionary<string, string> emailCache = new Dictionary<string, string>();
protected string GetUserEmail(string accountName)
{
if (emailCache.ContainsKey(accountName))
{
return(emailCache[accountName]);
}
lock(/* something */)
{
if (emailCache.ContainsKey(accountName))
{
return(emailCache[accountName]);
}
var email = GetEmailFromActiveDirectory(accountName);
emailCache.Add(accountName, email);
return(email);
}
}
Is the lock required? I assume so since multiple requests could be performing lookups simultaneously and end up trying to insert the same key into the same static dictionary.
If the lock is required, do I need to create a dedicated static object instance to use as the lock token, or is it safe to use the actual dictionary instance as the lock token?
Collections in .NET are not thread safe so the lock is indeed required. An alternative to using the dictionary one could use Concurrent dictionaries introduced in .NET 4.0
http://msdn.microsoft.com/en-us/library/dd287191.aspx
Yes, the lock is required as long as code on other threads can/will access the static object.
Yes, its safe to lock on the dictionary itself, as long as its not accessible via a public getter. Then the caller might use the object for locking itself and that might result in deadlocks. So i would recommend to use a separate object to lock in if your dictionary is somewhat public.
The lock is indeed required.
By using lock, you ensure that only one thread can access the critical section at one time, so an additional static object is not needed.
You can lock on the dictionary object itself, but I would simply use a object lock =new object(); as my lock.
MSDN documentation specify that you should never use the lock() statement over a public object that can be read or modified outside your own code.
I would rather use an object instance rather than the object you attempt to modify, specifically if this dictionnary has accessors that allows external code to access it.
I might be wrong here, I didn't write a line of C# since one year ago.
Since the dictionary is private, you should be safe to lock on it. The danger with locking (that I'm aware of) is that other code that you're not considering now could also lock on the object and potentially lead to a deadlock. With a private dictionary, this isn't an issue.
Frankly, I think you could eliminate the lock by just changing your code to not call the dictionary Add method, instead using the property set statement. Then I don't believe the lock at all.
UPDATE: The following is a block of code from the private Insert method on Dictionary, which is called by both the Item setter and the Add method. Note that when called from the item setter, the "add" variable is set to false and when called from the Add method, the "add" variable is set to true:
if (add)
{
ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_AddingDuplicate);
}
So it seems to me that if you're not concerned about overwriting values in your dictionary (which you wouldn't be in this case) then using the property setter without locking should be sufficient.
As far as I could see, additional object as a mutex was used:
private static object mutex = new object();
protected string GetUserEmail(string accountName)
{
lock (mutex)
{
// access the dictionary
}
}