Suppose I have singleton class that acts as a data cache. Multiple threads will read from the cache, and a single thread will periodically refresh it. It looks something like this:
public sealed class DataStore
{
public static DataStore Instance { get { return _instance; } }
public Dictionary<Foo, Bar> FooBar { get; private set; }
static DataStore() { }
private DataStore() { }
public void Refresh() {
FooBar = GetFooBarFromDB();
}
private static readonly DataStore _instance = new DataStore();
}
My question is essentially, is it safe to Refresh() while other threads may be accessing FooBar? Do I need to be using locks, or are my getting and setting operations atomic? Do I need to explicitly declare volatile fields to back up my properties?
P.S., If someone can think of a more descriptive title for this question, I would gladly welcome it.
Edit: Fixed my example to correct obviously non-atomic code.
Yes, in cases like that you need explicit synchronization, because another thread could get FooBar and start reading it before you have finished writing.
If you do this, however,
public void Refresh() {
var tmp = new Dictionary<Foo, Bar>();
// Fill out FooBar from DB
FooBar = tmp;
}
then you wouldn't need to add explicit synchronization, because the switch from one reference over to the other reference is atomic.
Of course there is an implicit assumption here that there is no writing outside the Refresh method.
EDIT: You also should switch from an auto-implemented property to a manually implemented property with a backing variable declared with volatile modifier.
Your example is not thread-safe. Dictionary is not a thread-safe class and any thread could be reading while Refresh is being executed. You can either put a lock around or use one of the thread-safe classes like ConcurrentDictionary.
Because you are exposing the dictionary publicly then you run into more issues with the code you have written around access to the methods on the dictionary itself. As #Icarus has pointed out you should use ConcurrentDictionary but I would argue that any form of locking around the instance will not help you.
You can easily get one thread adding to the collection while another is iterating over it.
EDIT
What I am saying.. never expose a static Dictionary or any other collection type. Always use the concurrent version
Well, we agree that your current code is not thread-safe.
So, you must use synchronization features, because FooBar is your critical section.
If you let it be public, you are expecting that people outside the DataStore class will act accordingly. However, this is a poor design decision.
So, I would suggest you to wrap everything into your current class, with something like this: What's the best way of implementing a thread-safe Dictionary?
Related
This pattern seems to be working for me to achieve thread locking in this thread unsafe environment.
However in terms of patterns and best practice (especially as I have figured it out myself), I'm not overly mad on exposing two collections that collate the same results. But the unsafe collection does need to be exposed publically and I don't want to make it private and have an 'AddResult(x)' method.
Is this the correct way to solve this problem?
public class UnsafeObject
{
public ObservableCollection<HighSpeedObject> ResultsUnsafe { get; set; }
/// Accessed by UI thread once every 100ms
public List<HighSpeedObject> Results
{
get
{
lock (_padlock)
{
return ResultsUnsafe.ToList();
}
}
}
private readonly static object _padlock = new object();
}
The instance of a ObservableCollectionz<T> class is not thread safe, so your solution is not stable.
The lock in the Results property only ensures that one thread at a time can use that property, but it doesn't protect the ResultsUnsafe property. The other threads can change the collection in the ResultsUnsafe property while the Results property is creating a list from it.
Side note: You are using a static member as identifier for a lock for non-static data. That means that the lock will prevent access in all instances of the class, not just the instance where the data is that you want to protect. To protect static data you should use a static member as identifier, and to protect instance data you should use an instance member as identifier.
I am reviewing an example code in a book and came across the following code(simplified).
In the code, when Subscribe(T subscriber) is called, the thread enters into a lock section.
and then, when code inside the lock calls AddToSubscribers(T subscriber) method, the method has another lock. why is this second lock necessary?
public abstract class SubscriptionManager<T> where T : class
{
private static List<T> subscribers;
private static void AddToSubscribers(T subscriber)
{
lock (typeof(SubscriptionManager<T>))
{
if (subscribers.Contains(subscriber))
return;
subscribers.Add(subscriber);
}
}
public void Subscribe(T subscriber)
{
lock (typeof(SubscriptionManager<T>))
{
AddToSubscribers(subscriber);
}
}
}
In that context, it isn't; however, since locks are re-entrant that can be useful to ensure that any other caller of AddToSubscribers observes the lock. Actually, for that reason I'd say "remove it from Subscribe and just let AddToSubscribers do the locking".
However! A lock on a Type is pretty dangerous. A field would be safer:
// assuming static is correct
private static readonly object syncLock = new object();
and lock(syncLock). Depending on when subscribers is assigned, you might also get away with lock(subscribers) (and no extra field).
I should also note that having an instance method add to static state is pretty.... unusual; IMO Subscribe should be a static method, since it has nothing to do with the current instance.
In the code you posted, it isn't necessary. But then again, the code you posted is incomplete - for example the subscribers list is never initialized.
Locking on typeof(SubscriptionManager) is probably not a good idea either - locking on the subscribers field would be better - but would require the subscribers field to be initialized, e.g.
private static List<T> subscribers = new List<T>();
You probably should read near that sample and see what book talks about.
For that particular case - no, second lock is unnecessary.
Note: The sample is dangerous since it locks on public object (type). Normally one locks on special private object so external code is not able to mistakenly introduce deadlocks by mistakenly locking on the same object.
I also faced a situation once where I had to use nested Lock.
My case was, the function of the second lock maybe called from elsewhere, since it was a static function. However, for your case it won't be necessary since each data member belongs to an Instance and not static..
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
}
}
I have put one question on MSDN forum but got two opposite answers. In general I am intersted how threading works with static classes. If my code calls this(below) static method from 10 threads at the same time, is it thread safe? I mean, how the code flows behind the scenes? Does every thread executes the code within itself (like I think it does with non-static classes) or it is different with static method and, because its static, all threads try to reach the code and collide? Thanks!
public static class A
{
static void Method(object parameter)
{
SqlCeConnection = .....
}
}
Link to MSDN question: Here
PS: I am sorry due to IE page errors I cannot click on "Add comment" or "Answer", Jon Skeet answer is good (as usually :)
It's exactly the same as with non-static classes. Being static doesn't affect anything really - except that static methods are generally expected to be thread-safe. They're not automatically thread-safe, but you should make sure that you implement them in a thread-safe manner.
If the code doesn't use any shared state, it should be fine. And yes, without any locking, all the threads can be executing the same method concurrently.
A nice example can be singleton pattern.In this all you need is a single instance for a given class and that can be made sure by making the constructor private and giving a static method or property to access the instance.Following code snippets highlight the same :-
class MyClass
{
private MyClass()
{
}
public static MyClass Instance
{
get
{
lock(typeof(MyClass))
{
if(__instance == null)
__instance = new MyClass();
}
return __instance;
}
}
}
Since the "Instance" method is marked static(thread consistent access) , but in multi threaded envoirnment you need to manully take care of it(using lock).