I have a dictionary that I maintain in C# which has a string to a class object mapping.
public class parent
{
public Dictionary<string, valueclass> clientToFileSystemMap {get;set;}
}
class valueclass
{
//some internal state
valueclass createclone()
{
create clone of this object and return
}
void update()
{
change state
}
}
Now there can be simultaneous threads which can be updating and cloning the same object at the same time. I want to synchronize the access so that clone does not return a half updated object.
One way that I found was create a private lock object in the class valueclass and acquire that lock before that operation. The other option would be to use [MethodImpl(MethodImplOptions.Synchronized)] as mentioned here - C# version of java's synchronized keyword?.
Another option could be to create a dictionary of objects similar to class objects and take lock on them.
What would be best way to do this?
You can use a ConcurrentDictionary to control access to the dictionary elements - but if sounds like you will need a private lock per object - as once a thread has a reference - the dictionary isn't really the issue.
private object privateLock = new object();
void update(){
lock(privateLock)
{
//change state
}
}
valueclass createclone(){
lock(privateLock)
{
//Clone
}
}
You can also use the SyncRoot provided by ICollection interface
http://msdn.microsoft.com/en-us/library/bb348148(v=vs.110).aspx
Related
I have the following code:
private static readonly object cacheLock = new object();
void foo(string key) {
lock(cacheLock) {
// perform calcs on a key
}
}
This works but blocks too much since there is only a single lock object - therefore I am looking for an approach where the lock object is named - to reduce contention.
I've tried the ConcurrentDictionary approach:
class NamedMonitor {
readonly ConcurrentDictionary<string, object> _dictionary = new ConcurrentDictionary<string, object>();
public object this[string name] => _dictionary.GetOrAdd(name, _ => new object());
}
And then:
private static NamedMonitor locker = new NamedMonitor();
lock (locker[name]) {
// ...
}
I am not a fan of that because the _dictionary inside the NamedMonitor class just grows unchecked.
I've also tried the Mutex object, which does allow named entries, but it's OS wide and therefore slower than other approaches.
What other approaches are there for named locks? Ideally I'd like to have code like this:
void foo(string key) {
lock(String.Intern(key)) {
// perform calcs on a key
}
}
but I am not sure that this is safe enough.
Instead of trying to introduce tricky approaches to implement a per-key level state protection inside the collection level functionality I'd suggest to make some separation of concerns. As per what can be deduced from your code snippets you have some functionality which operates on the per-key level and which has concurrent nature. This in turn implies that a per-key state you're trying to protect should be existing (already constructed at some point). Then why not to wrap this state and corresponding functionality into separate class which in addition would be responsible for the state protection from the race conditions instead of mixing the higher level protection of entire collection state with element level protection in the same unit and which may look like as follows:
public class Item
{
private readonly object _locker = new object();
public void Foo()
{
lock (_locker)
{
// perform calcs
}
}
}
void foo(string key)
{
// the getItem may also require protection but on the collection level
Item item = getItem(key);
item?.Foo();
}
As a per-key state is already there you're just wrapping it into the class which in that case is responsible of per-key state protection and implicitly controls the lock object lifecycle.
I have two classes A & B. Both are calling each other and having their own locks. I am getting a deadlock in one particular scenario. Here is the sample code.
class A : Interface1, Interface2
{
private B _bInstance = new B();
private object _aSync = new object();
private static A Instance;
private A(){}
public GetInstance()
{
if (Instance == null) Instance = new A();
return Instance;
}
void Method1()
{
lock(_aSync)
{
_bInstance.Method1();
}
}
void WriteData()
{
lock (_aSync)
{
WriteToFile();
}
}
}
class B
{
private object _bSync = new object();
void Method1()
{
lock (_bSync)
{
// Have some code here which need to protect my
// member variables.
A.GetInstance.WriteData();
}
}
void OneSecondTimerEvent()
{
lock (_bSync)
{
// Have some code here which need to protect my
// member variables.
A.GetInstance.WriteData();
}
}
}
How do I synchronize the OneSecondTimerEvent(), if One second timer gets triggered When the A.Method1() is being executed?
Yes, your code shows canonical example of deadlock - 2 resources waiting for each other to continue.
To resolve you can:
manually order lock statements (i.e. B never takes additional locks if A already have lock),
scope locks to only internal state of each class and never nest locks. In this case sometimes you'd need to copy state to call external methods.
use other synchronization primitives/constructs that allow such nesting (i.e. Reader-Writer locks).
Rather than try and solve this particular deadlock issue (which btw, is a classic result of locking things in an inconsistent order), I would strongly advise designing a better relationship between A and B. The fact you had to use a static instance to achieve a circular dependency should be a big clue you've done something wrong. Perhaps A and B should reference a 3rd class C, which is solely responsible for locking and writing the data? (Although it's difficult to say without a bit more context).
If I write a class like this:
public class LockBool
{
public bool validity = true;
}
And then I lock on such an object and change its validity field:
LockBool lockObj = GetTheLockObject();
lock(lockObj)
{
//release some resources
lockObj.validity = false;
}
So if another thread locks on the same object, it can read the validity for flow control.
lock(lockObj)
{
if(!validity)
return;
//do something here
}
Does it work as I expect, without throwing exception?
(If it works but it's bad practice, I also would like to know the details. Thanks!)
P.S.: The reason I tried to use the type with a bool field is to create variable number of lock objects. And it seems difficult to prevent other threads from acquiring the lock after I release resources. So a bool field can tell a thread if this lock is still valid, or it should be garbage-collected.
Please read this article.
using this kind of locking is discouraged, usually you should define a simple object varibale like
private static readonly object _lock;
with this kind of lock object you can sync between instances of your class (because it is static and shared between all instances) and no one can change its value (because it is readonly) and no one can use a lock on it from outside of class and make things go wrong (because it is private)
and if you want to just make the object thread safe (not all objects that are instantiated) you can remove the static and just use as many private object as you should.
UPDATE base on your comment
you can define a class like this
public class LockWrapper<T>
{
public T InsideClass { get; set; }
public readonly object _lock;
}
then use this when you need multiple instance of some class and want to lock on them separately
My question may sound like many others here but it has a flavor I didn't find.
I am trying to understand the following logic
A generic object
public class GenericClass
{
public static void DoSomething(Object lockObj)
{
lock(lockObj)
{
// do something here
}
}
}
Class A
internal class A
{
private static _aLock = new Object();
public void Do_A_Thing()
{
GenericClass.DoSomething(_aLock);
}
}
Class B
internal class B
{
private static _bLock = new Object();
public void Do_B_Thing()
{
GenericClass.DoSomething(_bLock);
}
}
I just hope to confirm if my explanation is correct:
If multiple threads of class "A" will attempt simultaneously access code in "genericClass" method "DoSomething", this method will be locked to all but one instance of class "A". But a single instance of class "B" will be able to proceed with execution any time. If class "B" will also have multiple instances execute, they will not interfere with class "A" locks.
Is this correct based on what you see above?
Yes, your description sounds correct. It is perhaps a little unusual to pass the lock object in, but it'll work fine. The only change I would suggest is to make the static fields readonly so you can't accidentally change the value to a different object reference.
Your conclusion is correct but it is not a good practice to pass locked object around. I suggest to put the lock inside class A and B respectively.
I suggest to write:
internal class A
{
private static readonly _aLock = new Object();
public void Do_A_Thing()
{
lock (_aLock)
{
GenericClass.DoSomething();
}
}
}
Do you have a specific reason to put the lock in another class? Maybe you can solve your problem in a different way?
Also keep in mind that in some conditions, maybe it is not your case, you can have a deadlock if class A and B call each other (A->B->A).
Yes, that is correct. The locks in A and the locks in B are completely unaware of each other. The code will only be blocked when there is another thread locking it with the same object as identifier.
If you are using generics, then something like
public class MyGadget<T>
{
static readonly SyncRoot = new object() ;
public T SynchronizedMethod()
{
lock ( SyncRoot )
{
SynchronizedMethodGuts() ;
}
}
}
should do what you want because MyGadget<Foo> and MyGadget<Bar> are different classes: they each have their own, different SyncRoot field.
I'm currently trying to implement a minimalistic ThreadLocal class. I know this is implemented in DotNet 4, but I'm in a situation where its not possible to upgrade.
My idea is to use a very simple class that holds a weak hashtable and just stores objects based on the current thread as key. (We have a custom implementation of a weak hashtable)
Do you think this is a viable approach or are there any threading issues to consider?
Is it ok to use current thread as a key, memory issues etc?
public class SimpleThreadLocal<T>
{
private readonly WeakHashtable _threadToValue;
public SimpleThreadLocal()
{
_threadToValue = new WeakHashtable();
}
public void Set(T value)
{
lock (this)
{
_threadToValue[Thread.CurrentThread] = value;
}
}
public T Get()
{
lock (this)
{
return (T) _threadToValue[Thread.CurrentThread];
}
}
}
Why not use the LogicalCallContext? Not only that it acts like a TLS, it is actually smarter and will keep your 'TLS' slot value in async callbacks and the like. See Logical Call Context: Flowing Data across Threads, AppDomains, and Processes and ExecutionContext vs SynchronizationContext.