C# Dictionary with ReaderWriterLockSlim - c#

I'm very new to multi-threading and for some reason this class is giving me more trouble than it should.
I am setting up a dictionary in the ASP.net cache - It will be frequently queried for individual objects, enumerated occasionally, and written extremely infrequently. I'll note that the dictionary data is almost never changed, I'm planning on letting it expire daily with a callback to rebuild from the database when it leaves the cache.
I believe that the enumeration and access by keys are safe so long as the dictionary isn't being written. I'm thinking a ReaderWriterLockSlim based wrapper class is the way to go but I'm fuzzy on a few points.
If I use Lock I believe that I can either lock on a token or the actual object I'm protecting. I don't see how to do something similar using the ReaderWriter Lock. Am I correct in thinking that multiple instances of my wrapper will not lock properly as the ReaderWriterLocks are out of each other's scope?
What is the best practice for writing a wrapper like this? Building it as a static almost seems redundant as the primary object is being maintained by the cache. Singleton's seem to be frowned upon, and I'm concerned about the above mentioned scoping issues for individual instances.
I've seen a few implementations of similar wrappers around but I haven't been able to answer these questions. I just want to make sure that I have a firm grasp on what I'm doing rather than cutting & pasting my way through. Thank you very much for your help!
**Edit: Hopefully this is a clearer summary of what I'm trying to find out- **
1. Am I correct in thinking that the lock does not affect the underlying data and is scoped like any other variable?
As an example lets say i have the following -
MyWrapperClass
{
ReaderWriterLockSlim lck = new ReaderWriterLockSlim();
Do stuff with this lock on the underlying cached dictionary object...
}
MyWrapperClass wrapA = new MyWrapperClass();
MyWrapperClass wrapB = new MyWrapperClass();
Am I right in thinking that the wrapA lock and wrapB lock won't interact, And that if wrapA & wrapB both attempt operations it will be unsafe?
2. If this is the case what is the best practice way to "share" the lock data?
This is an Asp.net app - there will be multiple pages that need to access the data which is why i'm doing this in the first place. What is the best practice for ensuring that the various wrappers are using the same lock? Should my wrapper be a static or singleton that all threads are using, if not what is the more elegant alternative?

You have multiple dictionary objects in the Cache, and you want each one locked independently. The "best" way is to just use a simple class that does it for you.
public class ReadWriteDictionary<K,V>
{
private readonly Dictionary<K,V> dict = new Dictionary<K,V>();
private readonly ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
public V Get(K key)
{
return ReadLock(() => dict[key]);
}
public void Set(K key, V value)
{
WriteLock(() => dict.Add(key, value));
}
public IEnumerable<KeyValuePair<K, V>> GetPairs()
{
return ReadLock(() => dict.ToList());
}
private V2 ReadLock<V2>(Func<V2> func)
{
rwLock.EnterReadLock();
try
{
return func();
}
finally
{
rwLock.ExitReadLock();
}
}
private void WriteLock(Action action)
{
rwLock.EnterWriteLock();
try
{
action();
}
finally
{
rwLock.ExitWriteLock();
}
}
}
Cache["somekey"] = new ReadWriteDictionary<string,int>();
There is also a more complete example on the help page of ReaderWriterLockSlim on MSDN. It wouldn't be hard to make it generic.
edit To answer your new questions -
1.) You are correct wrapA and wrapB will not interact. They both have their own instance of ReaderWriterLockSlim.
2.) If you need a shared lock amongst all your wrapper classes, then it must be static.

ConcurrentDictionary does everything you want and then some. Part of System.Concurrent.Collections

The standard way to lock is: object lck = new object(); ... lock(lck) { ... } in this instance the object lck represents the lock.
ReadWriterLockSlim isn't much different, its just in this case the actual ReadWriterLockSlim class represents the actual lock, so everywhere you would have used lck you now use your ReadWriterLockSlim.
ReadWriterLockSlim lck = new ReadWriterLockSlim();
...
lck.EnterReadLock();
try
{
...
}
finally
{
lck.ExitReadLock();
}

Related

C# Closures and a self made SpinLock.RecursiveEnter

actually what I'm simply trying to achieve is to get to know multithreading in C#.
SO i have this class called WeakeningEvictionary{TKey, TValue}, which has a private Dictionary{TKey, CachedValue{TValue}} that functions as the cache. CachedValue is a Wrapper that has a Strong- and WeakReference to TValue. After a predefined Time a Task is created to nullify the StrongReference and put it into WeakReference. I also have a HashSet implemented that keeps track of which keyValuePairs to evict. (added to when weakening happened, removed from when SetValue is called) Immediately after GC has done its Job another Task is created to evict all those mentioned Pairs.
Actually I wouldn't need a RecursiveLock for this, but I encountered Issues, when some stored Information is asked recursively because a construction series required so.
So I came up with this code: (Updated, was a not-going-to-work ExtensionMethod before)
public void RecursiveEnter(Action action)
{
if (_spinLock.IsHeldByCurrentThread)
{
action();
}
else
{
bool gotLock = false;
_spinLock.Enter(ref gotLock);//blocking until acquired
action();
if (gotLock) _spinLock.Exit();
}
}
So what I'm trying to do now is:
private void Evict()
{
RecursiveEnter(() =>
{
foreach (TKey key in toEvict)
{
_dict.Remove(key);
}
}
);
}
Alright what if I use
And my Question is: What are the Risks? And are Closures known to cause Issues when being used by Threads in this way?
Thanks for your Input ;-)
Right off the bat, the method call is 100% not going to work: SpinLock is a value type, you must pass it by reference (RecursiveEnter(ref SpinLock spinLock, Action action)) and not by value.
See for example https://learn.microsoft.com/en-us/dotnet/api/system.threading.spinlock?view=netframework-4.7.2#remarks
I'm not sure this is the best thing for you to use: you should start with a higher-level primitive (maybe a ReaderWriterLockSlim) and refine things only with careful testing and understanding.

Proper class definition and usage - thread safe - ASP.net

I wonder how to define a class properly and use it safely. I mean thread safely when thousands of concurrent calls are being made by every website visitor.
I made myself something like below but i wonder is it properly built
public static class csPublicFunctions
{
private static Dictionary<string, clsUserTitles> dicAuthorities;
static csPublicFunctions()
{
dicAuthorities = new Dictionary<string, clsUserTitles>();
using (DataTable dtTemp = DbConnection.db_Select_DataTable("select * from myTable"))
{
foreach (DataRow drw in dtTemp.Rows)
{
clsUserTitles tempCLS = new clsUserTitles();
tempCLS.irAuthorityLevel = Int32.Parse(drw["Level"].ToString());
tempCLS.srTitle_tr = drw["Title_tr"].ToString();
tempCLS.srTitle_en = drw["Title_en"].ToString();
dicAuthorities.Add(drw["authorityLevel"].ToString(), tempCLS);
}
}
}
public class clsUserTitles
{
private string Title_tr;
public string srTitle_tr
{
get { return Title_tr; }
set { Title_tr = value; }
}
private string Title_en;
public string srTitle_en
{
get { return Title_en; }
set { Title_en = value; }
}
private int AuthorityLevel;
public int irAuthorityLevel
{
get { return AuthorityLevel; }
set { AuthorityLevel = value; }
}
}
public static clsUserTitles returnUserTitles(string srUserAuthority)
{
return dicAuthorities[srUserAuthority];
}
}
Dictionary will be initialized only 1 time. No add remove update later.
Dictionary supports thread safe reading. Here is the proof from MSDN:
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.
So, if you are planning to only read data from it, it should work. However, I do not believe that your dictionary is filled only once and won't be modified during your application work. in this case, all other guys in this thread are correct, it is necessary to synchronize access to this dictionary and it is best to use the ConcurrentDictionary object.
Now, I want to say a couple of words about the design itself. If you want to store a shared data between users, use ASP.NET Cache instead which was designed for such purposes.
A quick look through your code and it seems to me that your first problem will be the publicly available dictionary dicAuthorities. Dictionaries are not thread safe. Depending on what you want to do with that Dictionary, you'll need to implement something that regulates access to it. See this related question:
Making dictionary access thread-safe?
As the others have said, Dictionary<TKey,TValue> is not inherently thread-safe. However, if your usage scenario is:
Fill the dictionary on startup
Use that dictionary as lookup while the application is running
Never add or remove values after startup
than you should be fine.
However, if you use .net 4.5, I would recommend making #3 explict, by using a ReadOnlyDictionary
So, your implementation might look like this (changed the coding style to more C# friendly)
private static readonly ReadOnlyDictionary<string, UserTitles> authorities;
static PublicFunctions()
{
Dictionary<string, UserTitles> authoritiesFill = new Dictionary<string, clsUserTitles>();
using (DataTable dtTemp = DbConnection.db_Select_DataTable("select * from myTable"))
{
foreach (DataRow drw in dtTemp.Rows)
{
UserTitles userTitle = new UserTitles
{
AuthorityLevel = Int32.Parse(drw["Level"].ToString()),
TitleTurkish = drw["Title_tr"].ToString();
TitleEnglish = drw["Title_en"].ToString();
}
authoritiesFill.Add(drw["authorityLevel"].ToString(), userTitle);
}
}
authorities = new ReadOnlyDictionary<string, UserTitles>(authoritiesFill);
}
I've also added a readonly modifier to the declaration itself, because this way you can be sure that it won't be replaced at runtime by another dictionary.
No you code is not thread safe.
[EDIT does not apply - set/created inside static constructor] Dictionary (as pointed by System Down answer) is not thread safe while being updated. Dictionary is not read only - hence no way to guarantee that it is not modified over time.
[EDIT does not apply - set/created inside static constructor] Initialization is not protected by any locks so you end-up with multiple initializations at the same time
Your entries are mutable - so it is very hard to reason if you get consistent value of each entry
[EDIT does not apply - only modified in static constructor] Field that holds dictionary not read-only - depending on code you may end-up with inconsistent data if not caching pointer to dictionary itself.
Side note: try to follow coding guidelines for C# and call classes starting with upper case MySpecialClass and have names that reflect purpose of the class (or clearly sample names).
EDIT: most of my points do not apply as the only initialization of the dictionary is inside static constructor. Which makes initialization safe from thread-safety point of view.
Note that initialization inside static constructor will happen at non-deterministic moment "before first use". It can lead to unexpected behavior - i.e. when access to DB may use wrong "current" user account.
The answer to your question is no, it's not thread safe. Dictionary is not a thread-safe collection. If you want to use a thread-safe dictionary then use ConcurrentDictionary.
Besides that, it's difficult to say whether your csPublicFunctions is thread-safe or not because it depends on how you handle your database connections inside the call to DbConnection.db_Select_DataTable
There is not thread-safe problem only with public Dictionary.
Yes, dictionary filling is thread-safe. But another modification of this dictionary is not thread safe. As was wrote above - ConcurrentDictionary could help.
Another problem that your class clsUserTitles is not thread-safe too.
If clsUserTitles is using only for reading you could make each property setter of clsUserTitles private. And initialize these properties from clsUserTitles constructor.

Ensure class is thread safe with only properties (any .NET 4.0 techniques specifically meant for this ?)

I have a class with two properties and two methods. Like the one below for example. (please ignore the data types or return types, it's just a typical scenario)
// The methods could be invoked by multiple threads
public class Stock
{
private static int FaceValue {get; set;}
private static int Percent (get; set;}
// method that updates the two properties
Public void UpdateStock()
{
FaceValue += 1;
Percent = FaceValue * 100;
}
// method that reads the two properties
public int[] GetStockQuote()
{
return new int[] { FaceValue, Percent};
}
}
I need to ensure this class is thread safe. I could use lock(obj) in both the methods as one technique to make it threadsafe but what would be the best technique to make it thread safe, considering the following:
There are only two properties that is read/updated. So, not sure if locking inside the methods is a good technique.
Will it be enough if I just make the properties thread safe rather than the methods or the class ?
Also, is there a way to make the whole class thread safe rather than individual methods or properties ? Any recommended lock techniques from .Net 4.0 ?
Just wondering if I am thinking through this right or may be I am over complicating it considering these. Many thanks in advance to help me get this clear.
Mani
In general, a lock is probably the simplest approach here.
A potentially better alternative would be to make this class immutable. If you make it so you can't change the values within the class once it's created, you no longer have to worry when reading the values, as there's no way for them to be modified.
In this case, that could be done by having a constructor that takes the two values, and changing UpdateStock to be more like:
public Stock GetUpdatedStock()
{
// Create a new instance here...
return new Stock(this.FaceValue + DateTime.Now.MilliSecond, this.FaceValue * 100);
}
Edit:
Now that you've made FaceValue and Percent static, you will need synchronization. A lock is likely the simplest option here.
With a single value, you could potentially use the Interlocked class to handle updates atomically, but there is no way to do an atomic update of both values*, which is likely required for the thread safety to be done properly. In this case, synchronizing via a lock will solve your issue.
*Note: This could possibly be done without a lock via Interlocked.CompareExchange if you put both values within a class, and exchanged the entire class instance - but that's likely a lot more trouble than it's worth.
There is no silver bullet solution for making thread safe, each scenario needs it's own solution. The most obvious is to use a lock, but in your example, you can simplify and use the Interlocked class and have this take care of making it an atomic operation:
public class Stock
{
private static int FaceValue {get; set;}
Public void UpdateStock()
{
//only a single property to update now
Interlocked.Increment(FaceValue);
}
// method that reads the two properties
public int[] GetStockQuote()
{
var currVal = FaceValue;
return new int[] { currVal, currVal * 100 };
}
}
See Interlocked on MSDN.

How do I make double-checked locking syntax less verbose?

In C#, I have the following extremely verbose syntax for pulling a simple list of items from a database:
if (malls == null)
{
lock (_lock)
{
if (malls == null)
{
using (var session = NhibernateHelper.OpenSession())
{
malls = session.CreateCriteria<Mall>()
.AddOrder(Order.Asc("Name")).List<Mall>();
CacheManager.Set(CACHE_KEY, malls, TimeSpan.FromMinutes(CACHE_DURATION));
}
}
}
}
I'm aware of the benefits of double checked locking and I strongly support its use, but it seems incredibly verbose. Can you recommend any syntax shortcuts or styles that might clean it up a bit?
Presumably you're using double-checked locking because you have a resource which you want initialized in a lazy, threadsafe manner.
Double-checked locking is a mechanism for achieving that, but as you've correctly noted, the verbosity of the mechanism is thoroughly overwhemling the meaning of the code.
When you have a mechanism that is obscuring the meaning, hide the mechanism by creating an abstraction. One way to do that would be to create a "lazy threadsafe instantiation" class and pass a delegate to it which does the operation you would like done in a lazy, threadsafe manner.
However, there's a better way. The better way is to not do that work yourself, but rather to let a world-class expert on threading do it for you. That way you don't have to worry about getting it right. Joe Duffy has to worry about getting it right. As Joe wisely says, rather than repeating the locking mechanism all over the place, write it once and then use the abstraction.
Joe's code is here:
http://www.bluebytesoftware.com/blog/PermaLink,guid,a2787ef6-ade6-4818-846a-2b2fd8bb752b.aspx
and a variation of this code will ship in the next version of the base class library.
To cut down on noise you can do this:
public List<Mall> Malls()
{
EnsureMallsInitialized();
return malls;
}
private void EnsureMallsInitialized()
{
if (malls == null) // not set
lock (_lock) // get lock
if (malls == null) // still not set
{
InitializeMalls();
}
}
private void InitializeMalls()
{
using (var session = NhibernateHelper.OpenSession())
{
malls = session.CreateCriteria<Mall>()
.AddOrder(Order.Asc("Name")).List<Mall>();
CacheManager.Set(CACHE_KEY, malls, TimeSpan.FromMinutes(CACHE_DURATION));
}
}

What are the Dangers of using a Singleton in a multithreaded application

I'm looking at using a singleton in a multithreaded Win service for doing logging, and wanted to know what are some of the problems I might encounter. I have already set up the get instance to handle syncing with
private static volatile Logging _instance;
private static object _syncRoot = new object();
private Logging(){}
public static Logging Instance
{
get
{
if (_instance==null)
{
lock(_syncRoot)
{
if (_instance == null)
{
_instance = new Logging();
}
}
}
return _instance;
}
}
Is there anything else I might need to worry about?
That looks pretty good to me.
See Implementing the Singleton Pattern in C# for more info.
Edit: Should probably put the return inside the lock, though.
This is more informational than anything else.
What you've posted is the double-checked locking algorithm - and what you've posted will work, as far as I'm aware. (As of Java 1.5 it works there, too.) However, it's very fragile - if you get any bit of it wrong, you could introduce very subtle race conditions.
I usually prefer to initialize the singleton in the static initializer:
public class Singleton
{
private static readonly Singleton instance = new Singleton();
public static Singleton Instance
{
get { return instance; }
}
private Singleton()
{
// Do stuff
}
}
(Add a static constructor if you want a bit of extra laziness.)
That pattern's easier to get right, and in most cases it does just as well.
There's more detail on my C# singleton implementation page (also linked by Michael).
As for the dangers - I'd say the biggest problem is that you lose testability. Probably not too bad for logging.
Singleton's have the potential to become a bottleneck for access to the resource embodied by the class, and force sequential access to a resource that could otherwise be used in parallel.
In this case, that may not be a bad thing, because you don't want multiple items writing to your file at the same instant, and even so I don't think your implementation will have that result. But it's something to be aware of.
You need to ensure that each method in the logger are safe to run concurrently, i.e. that they don't write to shared state without proper locking.
You are using double-checked locking what is considered a anti-pattern. Wikipedia has patterns with and without lazy initialization for different languages.
After creating the singleton instance you must of course ensure that all methods are thread-safe.
A better suggestion would be to establish the logger in a single-threaded setup step, so it's guaranteed to be there when you need it. In a Windows Service, OnStart is a great place to do this.
Another option you have is to used the System.Threading.Interlocked.CompareExchange(T%, T, T) : T method to switch out. It's less confusing and it's guaranteed to work.
System.Threading.Interlocked.CompareExchange<Logging>(_instance, null, new Logging());
There is some debate with respect to the need to make the first check for null use Thread.VolatileRead() if you use the double checked locking pattern and want it to work on all memory models. An example of the debate can be read at http://social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/b1932d46-877f-41f1-bb9d-b4992f29cedc/.
That said, I typically use Jon Skeet's solution from above.
I think if Logging instance methods are thread-safe there's nothing to worry about.

Categories

Resources