I have a class:
public class Checker
{
private HashSet<int> _hs = new HashSet<int>();
public bool Check(int a)
{
return Volatile.Read(ref _hs).Contains(a);
}
public void Update(IEnumerable<int> items)
{
Volatile.Write(ref _hs, new HashSet<int>(items));
}
}
Method Check is called from multiple threads quite often. Method Update is called from a single thread which monitors some source (database, http service etc.). Is this pattern of Volatile.Read / Volatile.Write usage correct?
If you mean "will Check always use the most up to date version of the field", then yes, as a side-effect of volatility this will be the case - and swapping the entire reference is much cheaper than constantly synchronizing (.NET ensures you can't have a torn reference so the reference swap is guaranteed to be atomic).
Note: the thread-safety in this scenario is strictly dependent on the fact that the hash-set is not mutated after it has been created and the reference swapped, which is what happens in the code in the question.
You can get the same result more conveniently, though, by declaring the field as volatile:
public class Checker
{
private volatile HashSet<int> _hs = new HashSet<int>();
public bool Check(int a) => _hs.Contains(a);
public void Update(IEnumerable<int> items) => _hs = new HashSet<int>(items);
}
Here is the code:
private int _count = 0;
public bool Ongoing
{
get
{
return _count > 0;
}
}
public void Method1(object param)
{
new Thread(new ParameterizedThreadStart(Method2)).Start(param);
}
private void Method2(object param)
{
_count++;
lock (_lock)
{
// Something
}
_count--;
}
The variable _count, as you can guess, is used to count up how many threads are locked. It is initialized to 0 and only modified inside this method and I use it to know if the class is doing something.
Now the problem: sometimes _count goes below 0. It's like _count++ get sometimes ignored.
This happens very seldom, like about once every 500 times I start this method, maybe even less.
Should I declare _count as volatile maybe?
You need to ensure the operations are applied atomically and the value isn't cached. To achieve the first you must use Interlocked.Increment and Interlocked.Decrement, for the second mark the field as volatile:
private volatile int _count = 0;
public bool Ongoing
{
get
{
return _count > 0;
}
}
public void Method1(object param)
{
new Thread(new ParameterizedThreadStart(Method2)).Start(param);
}
private void Method2(object param)
{
Interlocked.Increment(ref _count);
lock (_lock)
{
// Something
}
Interlocked.Decrement(ref _count);
}
As has been correctly pointed out in the accepted answer, you need to perform thread synchronization around the increment and decrement operations. This can be achieved with the Interlocked class.
However, you also need to use some memory synchronization mechanism to ensure that the up-to-date value is available to other threads. The MSDN documentation on volatile is abysmally wrong:
The MSDN documentation states that use of the volatile keyword ensures that the most up-to-date value is present in the field at all times. This is incorrect, since as we’ve seen, a write followed by a read can be reordered. (Joseph Albahari)
Specifically, the volatile keyword instructs the compiler to generate an acquire-fence every read from that field. However, the acquire-fence takes effect after the read, in order to prevent other reads/writes from being moved before it. This means that the read itself may be moved up, allowing a stale value to be retrieved the first time the variable is read.
Unfortunately, there is no clean method for reading an integer with the required memory barriers, but the nearest candidate is a redundant Interlocked.CompareExchange (see this answer):
private int _count = 0;
public bool Ongoing => Interlocked.CompareExchange(ref _count, 0, 0) > 0;
public void Method1(object param)
{
new Thread(new ParameterizedThreadStart(Method2)).Start(param);
}
private void Method2(object param)
{
Interlocked.Increment(ref _count);
lock (_lock)
{
// Something
}
Interlocked.Decrement(ref _count);
}
I want to make "count" thread safe in the following example.
In this, "process" is running constantly in a thread controlled in same class but "reset" is to be called by another thread through an object of the class.
namespace sample
{
class xyz
{
int count;
reset()
{
count=0;
}
process()
{
..
..
..
count +=10
..
..
}
}
}
EDIT 1: Is this a possible solution?
public class Xyz
{
private int count;
private static Object loackable = new Object();
public void Reset()
{
lock(lockable)
{
count = 0;
}
}
public void Process()
{
lock(loackable)
{
count += 10;
}
}
}
For basic counters you can use methods from. Interlocked class.
For anything more complicated wrap each operation on counter with lock using the same object to lock around single counter (either one static for all as you show in the question or instance objects as long as they paired to same counter all the time).
Note
you need to protect both. Read and write operations if you need correct value.
volatile can't help you to implement counters in general case as += is not atomic operation and multiple threads can read same value and than increment it so for two threads incrementing counter by 10 you can get counter incremented by 10 or twenty depending on timing. It may work in case of single write thread giving impression that code is correct.
You should add 'volatile' keyword for 'count' field. This ensure that the 'count' field will always be threading safe. (Read this)
public class Xyz
{
private volatile int count;
public void Reset()
{
count = 0;
}
public void Process()
{
count += 10;
}
}
And please, follow C# goodline!
Image this code:
You have 2 arrays, and you need to lock both of them in same moment (for any reason - you just need to keep locked both of them because they are somehow depending on each other) - you could nest the lock
lock (array1)
{
lock (array2)
{
... do your code
}
}
but this may result in a deadlock in case that someone in other part of your code would do
lock (array2)
{
lock (array1)
{
... do your code
}
}
and array 1 was locked - execution context switched - then array 2 was locked by second thread.
Is there a way to atomically lock them? such as
lock_array(array1, array2)
{
....
}
I know I could just create some extra "lock object" and lock that instead of both arrays everywhere in my code, but that just doesn't seem correct to me...
In general you should avoid locking on publicly accessible members (the arrays in your case). You'd rather have a private static object you'd lock on.
You should never allow locking on publicly accessible variable as Darin said. For example
public class Foo
{
public object Locker = new object();
}
public class Bar
{
public void DoStuff()
{
var foo = new Foo();
lock(foo.Locker)
{
// doing something here
}
}
}
rather do something like this.
public class Foo
{
private List<int> toBeProtected = new List<int>();
private object locker = new object();
public void Add(int value)
{
lock(locker)
{
toBeProtected.Add(value);
}
}
}
The reason for this is if you have multiple threads accessing multiple public synchronization constructs then run the very real possiblity of deadlock. Then you have to be very careful about how you code. If you are making your library available to others can you be sure that you can grab the lock? Perhaps someone using your library has also grabbed the lock and between the two of you have worked your way into a deadlock scenario. This is the reason Microsoft recommend not using SyncRoot.
I am not sure what you mean by lock to arrays.
You can easily perform operation on both arrays in single lock.
static readonly object a = new object();
lock(a){
//Perform operation on both arrays
}
I know that is wrong to use lock(this) or any shared object.
I wonder if this usage is OK?
public class A
{
private readonly object locker = new object();
private List<int> myList;
public A()
{
myList = new List<int>()
}
private void MethodeA()
{
lock(locker)
{
myList.Add(10);
}
}
public void MethodeB()
{
CallToMethodInOtherClass(myList);
}
}
public class OtherClass
{
private readonly object locker = new object();
public CallToMethodInOtherClass(List<int> list)
{
lock(locker)
{
int i = list.Count;
}
}
}
Is this thread safe? In OtherClass we lock with a private object so if the class A lock with its private lock can the list still change in the the lock block in OtherClass?
No, it's not thread safe. Add and Count may be executed at the "same" time. You have two different lock objects.
Always lock your own lock object when passing the list:
public void MethodeB()
{
lock(locker)
{
CallToMethodInOtherClass(myList);
}
}
No this is not thread safe. To make it thread safe you can use lock on static objects because they are shared between threads, this may cause deadlocks in the code but it can be handle by maintaining proper order for locking. There is a performance cost associated with lock so use it wisely.
Hope this helps
No, this is not thread-safe. A.MethodeA and OtherClass.CallToMethodInOtherClass are locking on different objects, so they're not mutually exclusive. If you need to protect the access to the list, don't pass it to external code, keep it private.
No, that is not thread-safe.
Your 2 methods are locking on 2 different objects, they will not lock out each other.
Because CallToMethodInOtherClass() only retrieves the value of Count nothing will go horribly wrong. But the lock() around it is useless and misleading.
If the method would make changes in the list you would have a nasty problem. To solve it, change MethodeB:
public void MethodeB()
{
lock(locker) // same instance as MethodA is using
{
CallToMethodInOtherClass(myList);
}
}
No, they have to lock the same object. With your code they both lock on a different and each call could be executed simultaneous.
To make the code thread safe place a lock in MethodeB or use the list itself as lock object.
It actually is thread-safe (purely as a matter of an implementation detail on Count), but:
Thread-safe snippets of code do not a thread-safe application make. You can combine different thread-safe operations into non-thread-safe operations. Indeed, much non-thread-safe code can be broken down into smaller pieces all of which are thread-safe on their own.
It's not thread-safe for the reason you were hoping, which means that extending it further would not be thread-safe.
This code would be thread-safe:
public void CallToMethodInOtherClass(List<int> list)
{
//note we've no locks!
int i = list.Count;
//do something with i but don't touch list again.
}
Call it with any list, and it'll give i a value based on the state of that list, regardless of what other threads are up to. It will not corrupt list. It will not give i an invalid value.
So while this code is also thread-safe:
public void CallToMethodInOtherClass(List<int> list)
{
Console.WriteLine(list[93]); // obviously only works if there's at least 94 items
// but that's nothing to do with thread-safety
}
This code would not be thread-safe:
public void CallToMethodInOtherClass(List<int> list)
{
lock(locker)//same as in the question, different locker to that used elsewhere.
{
int i = list.Count;
if(i > 93)
Console.WriteLine(list[93]);
}
}
Before going further, the two bits I described as thread-safe are not promised to be by the spec for List. Conservative coding would assume they are not thread-safe rather than depending upon implementation details, but I'm going to depend on the implementation details because it affects the question of how to use locks in an important way:
Because there is code operating on list that is not acquiring the lock on locker first, that code is not prevented from running concurrently with CallToMethodInOtherClass. Now, while list.Count is thread-safe and list[93] is tread-safe,* the combination of the two where we depend on the first to ensure that the second works is not thread-safe. Because code outside the lock can affect list, it's possible for code to call Remove or Clear in between Count assuring us that list[93] would work, and list[93] being called.
Now, if we know that list is only ever added to, that's fine, even if a resize is happening concurrently we'll end up with the value of list[93] either way. If something is writing to list[93] and it's a type that .NET will write to atomically (and int is one such type), we'll end up with either the old one or the new one, just as if we'd locked correctly we'd get the old or the new depending on which thread go the lock first. Again, this is an implementation detail not a specified promise, I'm stating this just to point out how the thread-safety given still results in non thread-safe code.
Moving this toward real code. We shouldn't assume that list.Count and list[93] is threadsafe because we weren't promised they would be and that could change, but even if we did have that promise, those two promises won't add up to a promise that they'd be thread-safe together.
The important thing is to use the same lock to protect blocks of code that can interfere with each other. Hence, consider the variant below that is guaranteed to be threadsafe:
public class ThreadSafeList
{
private readonly object locker = new object();
private List<int> myList = new List<int>();
public void Add(int item)
{
lock(locker)
myList.Add(item);
}
public void Clear()
{
lock(locker)
myList.Clear();
}
public int Count
{
lock(locker)
return myList.Count;
}
public int Item(int index)
{
lock(locker)
return myList[index];
}
}
This class is guaranteed to be thread-safe in everything it does. Without depending on any implementation details, there is no method here that will corrupt state or give incorrect results because of what another thread is doing with the same instance. The following code still doesn't work though:
// (l is a ThreadSafeList visible to multiple threads.
if(l.Count > 0)
Console.WriteLine(l[0]);
We've guaranteed the thread-safety of each call 100%, but we haven't guaranteed the combination, and we can't guarantee the combination.
There's two things we can do. We can add a method for the combination. Something like the following would be common for many classes specifically designed for multi-threaded use:
public bool TryGetItem(int index, out int value)
{
lock(locker)
{
if(l.Count > index)
{
value = l[index];
return true;
}
value = 0;
return false;
}
}
This makes the count test and the item retrieval part of a single operation which is guaranteed to be thread-safe.
Alternatively, and most often what we need to do, we have the lock happen at the place where the operations are grouped:
lock(lockerOnL)//used by every other piece of code operating on l
if(l.Count > 0)
Console.WriteLine(l[0]);
Of course, this makes the locks within ThreadSafeList redundant and just a waste of effort, space, and time. This is the main reason that most classes don't provide thread-safety on their instance members - since you can't meaningfully protect groups of calls on members from within the class, it's a waste of time trying to unless the thread-safety promises are very well specified and useful on their own.
To come back to the code in your question:
The lock in CallToMethodInOtherClass should be removed unless OtherClass has its own reason for locking internally. It can't make a meaningful promise that it won't be combined in a non-threadsafe way and adding more locks to a program just increases the complexity of analysing it to be sure there are no deadlocks.
The call to CallToMethodInOtherClass should be protected by the same lock as other operations in that class:
public void MethodeB()
{
lock(locker)
CallToMethodInOtherClass(myList);
}
Then as long as CallToMethodInOtherClass doesn't store myList somewhere it can be seen by other threads later on, it doesn't matter that CallToMethodInOtherClass isn't thread-safe because the only code that can access myList brings its own guarantee not to call it concurrently with other operations on myList.
The two important things are:
When something is described as "thread-safe", know just what it's promising by that, as there are different sorts of promise that fall under "thread-safe" and on its own it just means "I won't put this object into a nonsensical state", which while an important building block, is not a lot on its own.
Lock on groups of operations, with the same lock for each group that'll affect the same data, and guard the access to objects so that there can't possibly be another thread not playing ball with this.
*This is a very limited definition of thread-safe. Calling list[93] on a List<T> where T is a type that will be written and read atomically and we don't know whether it actually has at least 94 items is equally safe whether or not there are other threads operating on it. Of course, the fact that it can throw ArgumentOutOfRangeException in either case is not what most people would consider "safe", but the guarantee we have with multiple threads remains the same as with one. It's that we obtain a stronger guarantee by checking Count in a single thread but not in a multi-thread situation that leads me to describe that as not thread-safe; while that combo still won't corrupt state it can lead to an exception we'd assured ourselves couldn't happen.
Probably the easiest way to do the trick
public class A
{
private List<int> myList;
public A()
{
myList = new List<int>()
}
private void MethodeA()
{
lock(myList)
{
myList.Add(10);
}
}
public void MethodeB()
{
CallToMethodInOtherClass(myList);
}
}
public class OtherClass
{
public CallToMethodInOtherClass(List<int> list)
{
lock(list)
{
int i = list.Count;
}
}
}
Many of the answers have mentioned using a static readonly lock.
However, you really should try to avoid this static lock. It would be easy to create a deadlock where multiple threads are using the static lock.
What you could use instead is one of the .net 4 concurrent collections, these do provide some thread synchronisation on your behalf, so that you do not need to use the locking.
Take a look at the System.collections.Concurrent namespace.
For this example, you could use the ConcurrentBag<T> class.
Ass all the answers say these are different lock objects.
a simple way is to have a static lock object f.ex:
publc class A
{
public static readonly object lockObj = new object();
}
and in both classes use lock like:
lock(A.lockObj)
{
}