I was wondering if this statement would cause sync issues:
List<Character> characters = World.CharacterManager.Characters;
'Characters' is a class
'CharacterManager.Characters' would look something like this:
public List<Character> Characters
{
get
{
lock (this.objLock) { return this.characters; }
}
}
would this cause synchronization problems?
I want to use the referenced List to iterate through to find the character I am looking for.
The problem is that you are locking during the get, but once each thread has a reference to the collection, they can both act against it at the same time. Since the List<T>'s members aren't thread safe, you will encounter random bugs and exceptions when iterating, adding, removing, etc the collection.
You probably need to return a thread-safe collection. There isn't a 100% compatible thread-safe version, so you need to look through System.Collections.Concurrent and find a version that you can use.
The lock is useless that way. You will have to use a thread-safe collection such as Will suggested, or if you don't need write access you can expose only a read only version of your list like so:
public ReadOnlyCollection<Character> Characters {
get {
lock (locker) { return this.characters.AsReadOnly(); }
}
}
These collections cannot be modified, so if your Character type is immutable, you don't have any synchronization issues. If Character is mutable, you have again a problem, but you would have that problem even with a thread-safe collection. I hope you're aware of that. You can also expose the property returning an IList<Character>, but usually I find it better to tell the caller that the object is read only.
If you need write access, you could also do that by providing the appropriate methods at the scope of the CharacterManager and synchronize them. Jesse has written a nice example on how to do this.
EDIT: SyncRoot is not present on ICollection<T>.
Does the calling code actually need to be able to add and remove from the list? If so, that's not considered a best practice. Here's a (possible) way to implement without that requirement, instead putting the adding and removing of Character items into the CharacterManager class itself:
internal sealed class CharacterManager
{
private readonly IList<Character> characters = new List<Character>();
public ReadOnlyCollection<Character> Characters
{
get
{
lock (this.characters)
{
return this.characters.AsReadOnly();
}
}
}
public void Add(Character character)
{
lock (this.characters)
{
this.characters.Add(character);
}
}
public void Remove(Character character)
{
lock (this.characters)
{
this.characters.Remove(character);
}
}
}
If you are only wanting the caller to be able to enumerate the list then your property should have the type IEnumerable instead. If this is the case, then I would also make a copy of that list and return the copy. If the list is changed while you are enumerating it, then it will become invalid and throw an exception. The trade off is that the caller could possibly not have the latest version of the list. I would be inclined to convert it to a method named GetCharactersAsOfNow() instead of a property to help show that the caller needs to get an updated list for each call.
However if you are planning on allowing the caller to modify the list, then you have to make note that the list is not thread safe and require your caller to perform thread synchronization. Given that the caller now has this responsibility then you no longer need the lock in your property getter.
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.
In my app I have a List of objects. I'm going to have a process (thread) running every few minutes that will update the values in this list. I'll have other processes (other threads) that will just read this data, and they may attempt to do so at the same time.
When the list is being updated, I don't want any other process to be able to read the data. However, I don't want the read-only processes to block each other when no updating is occurring. Finally, if a process is reading the data, the process that updates the data must wait until the process reading the data is finished.
What sort of locking should I implement to achieve this?
This is what you are looking for.
ReaderWriterLockSlim is a class that will handle scenario that you have asked for.
You have 2 pair of functions at your disposal:
EnterWriteLock and ExitWriteLock
EnterReadLock and ExitReadLock
The first one will wait, till all other locks are off, both read and write, so it will give you access like lock() would do.
The second one is compatible with each other, you can have multiple read locks at any given time.
Because there's no syntactic sugar like with lock() statement, make sure you will never forget to Exit lock, because of Exception or anything else. So use it in form like this:
try
{
lock.EnterWriteLock(); //ReadLock
//Your code here, which can possibly throw an exception.
}
finally
{
lock.ExitWriteLock(); //ReadLock
}
You don't make it clear whether the updates to the list will involve modification of existing objects, or adding/removing new ones - the answers in each case are different.
To handling modification of existing items in the list, each object should handle it's own locking.
To allow modification of the list while others are iterating it, don't allow people direct access to the list - force them to work with a read/only copy of the list, like this:
public class Example()
{
public IEnumerable<X> GetReadOnlySnapshot()
{
lock (padLock)
{
return new ReadOnlyCollection<X>( MasterList );
}
}
private object padLock = new object();
}
Using a ReadOnlyCollection<X> to wrap the master list ensures that readers can iterate through a list of fixed content, without blocking modifications made by writers.
You could use ReaderWriterLockSlim. It would satisfy your requirements precisely. However, it is likely to be slower than just using a plain old lock. The reason is because RWLS is ~2x slower than lock and accessing a List would be so fast that it would not be enough to overcome the additional overhead of the RWLS. Test both ways, but it is likely ReaderWriterLockSlim will be slower in your case. Reader writer locks do better in scenarios were the number readers significantly outnumbers the writers and when the guarded operations are long and drawn out.
However, let me present another options for you. One common pattern for dealing with this type of problem is to use two separate lists. One will serve as the official copy which can accept updates and the other will serve as the read-only copy. After you update the official copy you must clone it and swap out the reference for the read-only copy. This is elegant in that the readers require no blocking whatsoever. The reason why readers do not require any blocking type of synchronization is because we are treating the read-only copy as if it were immutable. Here is how it can be done.
public class Example
{
private readonly List<object> m_Official;
private volatile List<object> m_Readonly;
public Example()
{
m_Official = new List<object>();
m_Readonly = m_Official;
}
public void Update()
{
lock (m_Official)
{
// Modify the official copy here.
m_Official.Add(...);
m_Official.Remove(...);
// Now clone the official copy.
var clone = new List<object>(m_Official);
// And finally swap out the read-only copy reference.
m_Readonly = clone;
}
}
public object Read(int index)
{
// It is safe to access the read-only copy here because it is immutable.
// m_Readonly must be marked as volatile for this to work correctly.
return m_Readonly[index];
}
}
The code above would not satisfy your requirements precisely because readers never block...ever. Which means they will still be taking place while writers are updating the official list. But, in a lot of scenarios this winds up being acceptable.
I'm putting together a custom SynchronizedCollection<T> class so that I can have a synchronized Observable collection for my WPF application. The synchronization is provided via a ReaderWriterLockSlim, which, for the most part, has been easy to apply. The case I'm having trouble with is how to provide thread-safe enumeration of the collection. I've created a custom IEnumerator<T> nested class that looks like this:
private class SynchronizedEnumerator : IEnumerator<T>
{
private SynchronizedCollection<T> _collection;
private int _currentIndex;
internal SynchronizedEnumerator(SynchronizedCollection<T> collection)
{
_collection = collection;
_collection._lock.EnterReadLock();
_currentIndex = -1;
}
#region IEnumerator<T> Members
public T Current { get; private set;}
#endregion
#region IDisposable Members
public void Dispose()
{
var collection = _collection;
if (collection != null)
collection._lock.ExitReadLock();
_collection = null;
}
#endregion
#region IEnumerator Members
object System.Collections.IEnumerator.Current
{
get { return Current; }
}
public bool MoveNext()
{
var collection = _collection;
if (collection == null)
throw new ObjectDisposedException("SynchronizedEnumerator");
_currentIndex++;
if (_currentIndex >= collection.Count)
{
Current = default(T);
return false;
}
Current = collection[_currentIndex];
return true;
}
public void Reset()
{
if (_collection == null)
throw new ObjectDisposedException("SynchronizedEnumerator");
_currentIndex = -1;
Current = default(T);
}
#endregion
}
My concern, however, is that if the Enumerator is not Disposed, the lock will never be released. In most use cases, this is not a problem, as foreach should properly call Dispose. It could be a problem, however, if a consumer retrieves an explicit Enumerator instance. Is my only option to document the class with a caveat implementer reminding the consumer to call Dispose if using the Enumerator explicitly or is there a way to safely release the lock during finalization? I'm thinking not, since the finalizer doesn't even run on the same thread, but I was curious if there other ways to improve this.
EDIT
After thinking about this a bit and reading the responses (particular thanks to Hans), I've decided this is definitely a bad idea. The biggest issue actually isn't forgetting to Dispose, but rather a leisurely consumer creating deadlock while enumerating. I now only read-lock long enough to get a copy and return the enumerator for the copy.
You are right, that's a problem. The finalizer is useless, it will run far too late to be of any use. The code should have deadlocked heavily before that anyway. Unfortunately, there's no way for you to tell the difference between the a foreach calling your MoveNext/Current members or the client code using them explicitly.
No fix, don't do this. Microsoft didn't do it either, they had plenty of reason to back in .NET 1.x. The only real thread-safe iterator you can make is one that creates a copy of the collection object in the GetEnumerator() method. The iterator getting out of sync with the collection is no joy either though.
This seems far too error-prone to me. It encourages situations in which a lock is implicitly/silently taken out, in a way that is not clear to the reader of the code, and makes it likely that a crucial fact about the interface will be misunderstood.
Usually it's a good idea to duplicate common patterns - represent an enumerable collection with IEnumerable<T> that is disposed when you're done with it - but the added ingredient of taking out a lock makes a big difference, unfortunately.
I'd suggest the ideal approach would be to not offer enumeration on collections shared between threads at all. Try to design the whole system so it isn't needed. Obviously this is going to be a crazy pipe-dream sometimes.
So the next best thing would be to define a context within which an IEnumerable<T> is temporarily available, while the lock exists:
public class SomeCollection<T>
{
// ...
public void EnumerateInLock(Action<IEnumerable<T>> action) ...
// ...
}
That is, when the user of this collection wants to enumerate it, they do this:
someCollection.EnumerateInLock(e =>
{
foreach (var item in e)
{
// blah
}
});
This makes the lifetime of the lock explicitly stated by a scope (represented by the lambda body, working much like a lock statement), and impossible to extend accidentally by forgetting to dispose. It's impossible to abuse this interface.
The implementation of the EnumerateInLock method would be like this:
public void EnumerateInLock(Action<IEnumerable<T>> action)
{
var e = new EnumeratorImpl(this);
try
{
_lock.EnterReadLock();
action(e);
}
finally
{
e.Dispose();
_lock.ExitReadLock();
}
}
Notice how the EnumeratorImpl (which needs no particular locking code of its own) is always disposed before the lock is exited. After disposal, it throws ObjectDisposedException in response to any method call (other than Dispose, which is ignored.)
This means that even if there is an attempt to abuse the interface:
IEnumerable<C> keepForLater = null;
someCollection.EnumerateInLock(e => keepForLater = e);
foreach (var item in keepForLater)
{
// aha!
}
This will always throw, rather than failing mysteriously sometimes based on the timing.
Using a method that accepts a delegate like this is a general technique for managing resource lifetimes commonly used in Lisp and other dynamic languages, and while it is less flexible than implementing IDisposable, that reduced flexibility is often a blessing: it removes the concern over clients "forgetting to dispose".
Update
From your comment, I see that you need to be able to hand a reference to the collection to an existing UI framework, which will therefore expect to be able to use the normal interface to a collection, i.e. directly get an IEnumerable<T> from it and be trusted to clean it up quickly. In which case, why worry? Trust the UI framework to update the UI and dispose the collection rapidly.
Your only other realistic option is simply to make a copy of the collection when the enumerator is requested. That way, the lock only needs to be held when the copy is being made. As soon as it's ready, the lock is released. This may be more efficient if the collections are usually small, so the overhead of the copy is less than the performance saving due to shorter locks.
It's tempting (for about a nanosecond) to suggest that you use a simple rule: if the collection is smaller than some threshold, make the copy, otherwise do it in your original way; choose the implementation dynamically. That way you get the optimum performance - set the threshold (by experiment) such that the copy is cheaper than holding the lock. However, I'd always think twice (or a billion times) about such "clever" ideas in threaded code, because what if there is an abuse of the enumerator somewhere? If you forget to dispose it, you won't see a problem unless it's a large collection... A recipe for hidden bugs. Don't go there!
Another potential drawback with the "expose a copy" approach is that clients will undoubtedly fall under the assumption that if an item is in the collection it is exposed to the world, but as soon as it is removed from the collection it is safely hidden. This will now be wrong! The UI thread will obtain an enumerator, then my background thread will remove the last item from it, and then begin mutating it in the mistaken belief that, because it was removed, no one else can see it.
So the copying approach requires every item on the collection to effectively have its own synchronization, where most coders will assume that they can shortcut this by using the collection's synchronization instead.
I had to do this recently. The way I did it was to abstract it so that there is an inner object (reference) that contains both the actual list/array and the count (and a GetEnumerator() implementation; then I can do lock-free, thread-safe enumeration by having:
public IEnumerator<T> GetEnumerator() { return inner.GetEnumerator();}
The Add etc need to be synchronized, but they change the inner reference (since reference updates are atomic, you don't need to synchronize GetEnumerator()). This then means that any enumerator will return as many items as were there when the enumerator was created.
Of course, it helps that my scenario was simple, and my list was Add only... if you need to support mutate / remove then it is much trickier.
In the must used IDisposable implementation, you create a protected Dispose(bool managed) method which always disposes the unmanaged resources you use. By calling your protected Dispose(false) method from your finalizer, you'll dispose the lock as required. The lock is managed, do you'll only dispose it when Dispose(true) is called, where true means that managed objects need to be disposed. Otherwise, when the public Dispose() is called explicitly, it calls the protected Dispose(true) and also GC.SuppressFinalize(this) to prevent the finalizer from running (because there is nothing to dispose of anymore).
Because you never know when the user is done with the enumerator, you have no other option than documenting that the user has to dispose the object. You might want to propose that the user uses a using(){ ... } construction, which automatically disposes the object when done.
I am a threading noob and I am trying to write a custom thread safe generic list class in C# (.NET 3.5 SP1). I've read Why are thread safe collections so hard?. After reviewing the requirements of the class I think I only need to safely add to the list and return the list. The example shows pretty much all I want except it lacks the return list method therefore I've written my own public method like below:
Update: based on suggestions given I've reviewed my requirements and therefore simplified the class to as below:
public sealed class ThreadSafeList<T>
{
private readonly IList<T> list = new List<T>();
private readonly object lockable = new object();
public void Add(T t)
{
lock (lockable)
{
list.Add(t);
}
}
public IList<T> GetSnapshot()
{
IList<T> result;
lock (lockable)
{
result = new List<T>(list);
}
return result;
}
}
Agree with #jrista. There's a semantics issue you need to resolve, and why is it called Translate()? What is the intent?
A - current code - return a read-only wrapper of the internal list
return new ReadOnlyCollection<T>(list);
You still have threading issues if the original list is changed if another thread is iterating over the list. As long as you're aware of this, it isn't a huge issue.
B - a read-only copy.
return new List<T>(list).AsReadOnly();
This list has no threading issues because nothing modifies the new list. The only reference held is by the ReadOnlyCollection<T> wrapper.
C - a normal (writable) copy
return new List<T>(list);
Returns a new list, and the caller can do what they wish to their list without affecting the original list, and changes to the original list do not affect this list.
Does it matter if another consumer grabs a copy of the list and then modifies their copy? Do consumers need to see changes to the list? Do you just need a thread-safe enumerator?
public IEnumerator<T> ThreadSafeEnumerator()
{
List<T> copy;
lock(lockable)
copy = new List<T>(list);
foreach (var value in copy)
yield return value;
}
In my experience you have to use your brain when it comes to thread-safety and not rely on solutions such as these.
in short, it depends on what the receiver of the list is going to be doing with it.
The Translate() method looks correct. Using the lock you are preventing others from adding or otherwise modifying your list while you are in Translate/AddRange.
I think there might be a problem with your IsReadyOnly property though. You use a lock when reading/writing the property internally. But there also is a public getter which is not locked. It might happen that thread 1 calls MarkAsReadOnly while a second thread might still get false when looking at IsReadOnly. I'd use a normal property instead and either lock in the getter or use a volatile bool field.
You can use SynchronizedCollection.
http://msdn.microsoft.com/en-us/library/ms668265.aspx