In multi-threaded code, when an instance may be read or written by multiple threads, they need to be locked on to perform these operations safely.
To avoid the repetition of creating an object to lock on and writing a bunch of lock statements through code, I've created a generic class to handle the locking.
Am I missing anything, conceptually? This should work, right?
public class Locked<T> where T : new()
{
private readonly object locker = new object();
private T value;
public Locked()
: this(default(T))
{ }
public Locked(T value)
{
this.value = value;
}
public T Get()
{
lock (this.locker)
{
return this.value;
}
}
public void Set(T value)
{
lock (this.locker)
{
this.value = value;
}
}
}
And an example of it being used in a class:
private Locked<bool> stopWorkerThread = new Locked<bool>();
public void WorkerThreadEntryPoint()
{
while (true)
{
if (this.stopWorkerThread.Get())
{
break;
}
Also, how would I test something like this, in an automated way (e.g. create a unit test)?
Lastly, what can I do to implement a ++ and -- operator, to avoid this:
this.runningThreads.Set(this.runningThreads.Get() + 1);
That only locks for the duration of the get/set; of course, in many common cases this will be atomic anyway, simply due to to data size.
However, in reality most locks need to span more than this, in the same way that collections locking over just the Add etc don't help much - a caller typically needs a single lock to span the "is it there? if so update, else add" sequence.
For something as simple as a bool, "volatile" might solve the problem a lot more simply - especially if it is just for a loop exit.
You might also want to consider [MethodImpl(MethodImplOptions.Synchronized)] - although personally I prefer a private lock object (like you have used) to prevent issues with external people locking on the object (the above uses "this" as the lock).
For unit testing this, you'd need something to prove it broken first - which would be hard since the operations are so small (and already atomic for most data types). One of the other things it avoids (that volatile also fixes) is caching in a register, but again that is an optimisation and hard to force to prove it is broken.
If you are interested in a lock-wrapper, you might consider existing code like this.
Your code above has quite a few potential and real multi-threading issues, and I wouldn't use something like it in a real-world situation. For example:
this.runningThreads.Set(this.runningThreads.Get() + 1);
There is a pretty obvious race condition here. When the Get() call returns, the object is no longer locked. To do a real post or pre increment, the counter would need to be locked from before the Get to after the Set.
Also you don't always need to do a full lock if all you are doing is synchronous reads.
A better lock interface would (I think) require you to explicitly lock the instance where you need to do it. My experience is mainly with C++ so I can't recommend a full implementation, but my preferred syntax might look something like this:
using (Locked<T> lock = Locked<T>(instance))
{
// write value
instance++;
}
// read value
print instance;
Related
It is a little bit confusing. In C# for multithread managing we have mutex and we have lock and in addition I found such lock RAII implementation
public class ReaderWriterLockSlim_ScopedLockRead : IDisposable
{
ReaderWriterLockSlim m_myLock;
public ReaderWriterLockSlim_ScopedLockRead(ReaderWriterLockSlim myLock)
{
m_myLock = myLock;
m_myLock.EnterReadLock();
}
public void Dispose()
{
m_myLock.ExitReadLock();
}
}
public class ReaderWriterLockSlim_ScopedLockWrite : IDisposable
{
ReaderWriterLockSlim m_myLock;
public ReaderWriterLockSlim_ScopedLockWrite(ReaderWriterLockSlim myLock)
{
m_myLock = myLock;
m_myLock.EnterWriteLock();
}
public void Dispose()
{
m_myLock.ExitWriteLock();
}
}
}
I would like to understand the difference between them, as for me mutex is a first multithreading managing implementation you need to call mutex.lock() and then don't forget to call mutex.release() it is usually not so suitable to call mutex.release() because you can get an error at the middle of execution, so here we have lock(obj){} as far as I see it is kind of RAII object with the same behavior but if you get error at the middle under the hood it will call mutex.release() and all nice.
But what about the last custom implementaion that I posted? It looks like the same with lock(obj){}, just with a difference that we have read and write behavior, like in write state it is possible that a few threads get accesses to method and with read state just one by one...
Am I right here?
So for locking it's important that every lock that is acquired is also released (no matter if the code it was locking had any exceptions). So normally, no matter what lock you use, it'll look something like this:
myLock.MyAcquireMethod();
try
{
//...
}
finally
{
myLock.MyReleaseMethod();
}
Now for the Monitor locking mechanism in c# they have a keyword to make it easier: lock.
which basically wraps the acquiring and releasing in one lock code-block.
So this:
lock(myObj)
{
//...
}
Is just a more convenient way of writing this:
Monitor.Enter(myObj);
try
{
//...
}
finally
{
Monitor.Exit(myObj);
}
Sadly for the other locks (and because Monitor has it's limitations we don't always want to use it) we don't have such a handy short way of doing the whole thing, and to solve that the ReaderWriterLockSlim_ScopedLockRead wrapper implements IDisposable that gives you this try finally mechanism (using also guarantees that Dispose() is called on the IDisposable no matter if the code ran to completion or an exception occurred.
So instead of:
m_myLock.EnterWriteLock();
try
{
//...
}
finally
{
m_myLock.ExitWriteLock();
}
You're now able to do this:
using(new ReaderWriterLockSlim_ScopedLockRead(m_myLock))
{
//...
}
Hope this answers your question!
As a bonus a warning on the Monitor class of c#. This locking mechanism is re-entrant on a thread level. Meaning the thread holding the lock is allowed to acquire it multiple times (though it also has to release it multiple times), which allows you to do something like this:
private readonly object _myLock = new object();
public void MyLockedMethod1()
{
lock(_myLock)
{
MyLockedMethod2();
}
}
public void MyLockedMethod2()
{
lock(_myLock)
{
//...
}
}
So no matter if MyLockedMethod2 is called directly or through MyLockedMethod1 (that might need the lock for other stuff as well) you can have thread-safety.
However these days a lot of people use async/await where a method can be continued on a different thread, which can break the Monitor if the thread that acquired it is not the thread releasing it, so I advise you not to use something like this:
public async Task MyLockedMethod()
{
lock(_myLock)
{
await MyAsyncMethod();
}
}
Anyway there is a lot of documentation about this if you would like to learn more.
This is not it at all. The Read Writer lock is an implementation used in a specific context.
All can read at any time without one blocking the other, but blocking anyone who wants to write.
None can read or write when there is even one writing at that time
It is exactly as wikipedia describes it here and non-specific for C# or any other language. This is just the C# flavor of a ReadWriter lock
is a synchronization primitive that solves one of the readers–writers problems. An RW lock allows concurrent access for read-only operations, while write operations require exclusive access.
Check Microsoft docs here for more information
I've seen many examples of the lock usage, and it's usually something like this:
private static readonly object obj = new object();
lock (obj)
{
// code here
}
Is it possible to lock based on a property of a class? I didn't want to lock globally for any calls to the method with the lock statement, I'd like to lock only if the object passed as argument had the same property value as another object which was being processed prior to that.
Is that possible? Does that make sense at all?
This is what I had in mind:
public class GmailController : Controller
{
private static readonly ConcurrentQueue<PushRequest> queue = new ConcurrentQueue<PushRequest>();
[HttpPost]
public IActionResult ProcessPushNotification(PushRequest push)
{
var existingPush = queue.FirstOrDefault(q => q.Matches(push));
if (existingPush == null)
{
queue.Enqueue(push);
existingPush = push;
}
try
{
// lock if there is an existing push in the
// queue that matches the requested one
lock (existingPush)
{
// process the push notification
}
}
finally
{
queue.TryDequeue(out existingPush);
}
}
}
Background: I have an API where I receive push notifications from Gmail's API when our users send/receive emails. However, if someone sends a message to two users at the same time, I get two push notifications. My first idea was querying the database before inserting (based on subject, sender, etc). In some rare cases, the query of the second call is made before the SaveChanges of the previous call, so I end up having duplicates.
I know that if I ever wanted to scale out, lock would become useless. I also know I could just create a job to check recent entries and eliminate duplicates, but I was trying something different. Any suggestions are welcome.
Let me first make sure I understand the proposal. The problem given is that we have some resource shared to multiple threads, call it database, and it admits two operations: Read(Context) and Write(Context). The proposal is to have lock granularity based on a property of the context. That is:
void MyRead(Context c)
{
lock(c.P) { database.Read(c); }
}
void MyWrite(Context c)
{
lock(c.P) { database.Write(c); }
}
So now if we have a call to MyRead where the context property has value X, and a call to MyWrite where the context property has value Y, and the two calls are racing on two different threads, they are not serialized. However, if we have, say, two calls to MyWrite and a call to MyRead, and in all of them the context property has value Z, those calls are serialized.
Is this possible? Yes. That doesn't make it a good idea. As implemented above, this is a bad idea and you shouldn't do it.
It is instructive to learn why it is a bad idea.
First, this simply fails if the property is a value type, like an integer. You might think, well, my context is an ID number, that's an integer, and I want to serialize all accesses to the database using ID number 123, and serialize all accesses using ID number 345, but not serialize those accesses with respect to each other. Locks only work on reference types, and boxing a value type always gives you a freshly allocated box, so the lock would never be contested even if the ids were the same. It would be completely broken.
Second, it fails badly if the property is a string. Locks are logically "compared" by reference, not by value. With boxed integers, you always get different references. With strings, you sometimes get different references! (Because of interning being applied inconsistently.) You could be in a situation where you are locking on "ABC" and sometimes another lock on "ABC" waits, and sometimes it does not!
But the fundamental rule that is broken is: you must never lock on an object unless that object has been specifically designed to be a lock object, and the same code which controls access to the locked resource controls access to the lock object.
The problem here is not "local" to the lock but rather global. Suppose your property is a Frob where Frob is a reference type. You don't know if any other code in your process is also locking on that same Frob, and therefore you don't know what lock ordering constraints are necessary to prevent deadlocks. Whether a program deadlocks or not is a global property of a program. Just like you can build a hollow house out of solid bricks, you can build a deadlocking program out of a collection of locks that are individually correct. By ensuring that every lock is only taken out on a private object that you control, you ensure that no one else is ever locking on one of your objects, and therefore the analysis of whether your program contains a deadlock becomes simpler.
Note that I said "simpler" and not "simple". It reduces it to almost impossible to get correct, from literally impossible to get correct.
So if you were hell bent on doing this, what would be the right way to do it?
The right way would be to implement a new service: a lock object provider. LockProvider<T> needs to be able to hash and compare for equality two Ts. The service it provides is: you tell it that you want a lock object for a particular value of T, and it gives you back the canonical lock object for that T. When you're done, you say you're done. The provider keeps a reference count of how many times it has handed out a lock object and how many times it got it back, and deletes it from its dictionary when the count goes to zero, so that we don't have a memory leak.
Obviously the lock provider needs to be threadsafe and needs to be extremely low contention, because it is a mechanism designed to prevent contention, so it had better not cause any! If this is the road you intend to go down, you need to get an expert on C# threading to design and implement this object. It is very easy to get this wrong. As I have noted in comments to your post, you are attempting to use a concurrent queue as a sort of poor lock provider and it is a mass of race condition bugs.
This is some of the hardest code to get correct in all of .NET programming. I have been a .NET programmer for almost 20 years and implemented parts of the compiler and I do not consider myself competent to get this stuff right. Seek the help of an actual expert.
Although I find Eric Lippert's answer fantastic and marked it as the correct one (and I won't change that), his thoughts made me think and I wanted to share an alternative solution I found to this problem (and I'd appreciate any feedbacks), even though I'm not going to use it as I ended up using Azure functions with my code (so this wouldn't make sense), and a cron job to detected and eliminate possible duplicates.
public class UserScopeLocker : IDisposable
{
private static readonly object _obj = new object();
private static ICollection<string> UserQueue = new HashSet<string>();
private readonly string _userId;
protected UserScopeLocker(string userId)
{
this._userId = userId;
}
public static UserScopeLocker Acquire(string userId)
{
while (true)
{
lock (_obj)
{
if (UserQueue.Contains(userId))
{
continue;
}
UserQueue.Add(userId);
return new UserScopeLocker(userId);
}
}
}
public void Dispose()
{
lock (_obj)
{
UserQueue.Remove(this._userId);
}
}
}
...then you would use it like this:
[HttpPost]
public IActionResult ProcessPushNotification(PushRequest push)
{
using(var scope = UserScopeLocker.Acquire(push.UserId))
{
// process the push notification
// two threads can't enter here for the same UserId
// the second one will be blocked until the first disposes
}
}
The idea is:
UserScopeLocker has a protected constructor, ensuring you call Acquire.
_obj is private static readonly, only the UserScopeLocker can lock this object.
_userId is a private readonly field, ensuring even its own class can't change its value.
lock is done when checking, adding and removing, so two threads can't compete on these actions.
Possible flaws I detected:
Since UserScopeLocker relies on IDisposable to release some UserId, I can't guarantee the caller will properly use using statement (or manually dispose the scope object).
I can't guarantee the scope won't be used in a recursive function (thus possibly causing a deadlock).
I can't guarantee the code inside the using statement won't call another function which also tries to acquire a scope to the user (this would also cause a deadlock).
I posted an earlier question about returning collections, and the topic of thread safety came up. I was given this link to do some more reading, and I found this particular line:
In general, avoid locking on a public type, or instances beyond your
code's control.
First, correct me if I'm wrong, but doesn't the example that Microsoft give lock on a public type, the balance variable?
Secondly, how would I go about locking my own getter/setter property. Suppose I have the following class:
private int ID;
public Person(int id)
{
this.Identification= id;
}
public int Identification
{
get { return this.ID; }
private set
{
if (value == 0)
{
throw new ArgumentNullException("Must Include ID#");
}
this.ID = value;
}
}
The getter is public correct? Only the setter is declared private. So, how would I lock, or make my getter/setter properties thread safe?
you should define a variable in Person class like this
private readonly object _lock_ = new Object();
if you want to make synchronization over all instances of Person you should make it static.
then when you want to lock you can do it like this
lock(_lock_) //whose there? it's me, I kill you! oops sorry that was knock knock
{
//do what you want
}
I suggest you to read this article: 1
When you need to lock on a variable, you need to lock around every place where the variable is used. A lock is not for a variable - it's for a region of code where a variable is used.
It doesn't matter if you 'only read' in one place - if you need locking for a variable, you need it everywhere where that variable is used.
An alternative to lock is the Interlocked class - this uses processor-level primitives for locking that's a bit faster. Interlocked, however cannot protect multiple statements (and having 2 Interlocked stataments is not the same as having those 2 statements inside a single lock).
When you lock, you must lock on an instance of a reference type (which, in most cases (but not always), should also be a static instance). This is to ensure that all locks are actually taken out on the same instance, not a copy of it. Obviously, if you're using a copy in different places, you're not locking the same thing so your code won't be correctly serialized.
For example:
private static readonly object m_oLock = new object ();
...
lock ( m_oLock )
{
...
}
Whether it's safe to use a non-static lock requires detailed analysis of the code - in some situations, it leads to more parallelism because the same region of code is locked less but the analysis of it could be very tricky - if you're unsure, just use a static lock object. The cost of taking an open lock is minimal but incorrect analysis may lead to errors that take ages to debug.
Edit:
Here's an example showing how to lock property access:
private int ID; // do NOT lock on value type instances
private static readonly object Lock = new object ();
public Person(int id)
{
this.Identification = id;
}
public int Identification
{
get
{
lock ( Lock )
{
return this.ID;
}
}
private set
{
if (value == 0)
throw new ArgumentNullException("Must Include ID#");
lock ( Lock )
{
this.ID = value;
}
}
}
Since your property only does a trivial get/set operation, you can try using Interlocked.CompareExchange instead of a full lock - it will make things slightly faster. Keep in mind, though, that an interlocked operation is not the same as a lock.
Edit 2:
Just one more thing: a trivial get / set on an int doesn't need a lock - both reading and writing a 32-bit value (in and of itself) is already atomic. So this example is too simple - as long as you're not trying to use ID in multiple operations that should be completed in an atomic fashion, the lock is not needed. However, if your real code is actually more complicated with ID being checked and set, you may need locking and you'll need to lock around all the operations that make up the atomic operation. This means that you may have to pull the lock out of the getter / setter - 2 locks on a get/set pair of a variable is not the same as a single lock around them.
The answer to your first question about the Microsoft article:
No. The article doesn't lock on the balance variable. It locks on the private thisLock variable. So the example is good.
Secondly, based on the code you have posted, you don't need to add any locking to make your class thread safe, because your data is immutable. Once you create an instance of Person and set the value for the Identification property from within the constructor, your class design doesn't allow for that property to change again. That's immutability, and that in itself provides thread safety. So you don't need to bother with adding locks and such. Again, assuming your code sample is accurate.
EDIT:
This link may be useful to you.
I haven't had any issues using the same lock for multiple methods so far, but I'm wondering if the following code might actually have issues (performance?) that I'm not aware of:
private static readonly object lockObj = new object();
public int GetValue1(int index)
{
lock(lockObj)
{
// Collection 1 read and/or write
}
}
public int GetValue2(int index)
{
lock(lockObj)
{
// Collection 2 read and/or write
}
}
public int GetValue3(int index)
{
lock(lockObj)
{
// Collection 3 read and/or write
}
}
The 3 methods and the collections are not related in anyway.
In addition, will it be a problem if this lockObj is also used by a singleton (in Instance property) ?
Edit: To clarify my question on using the same lock object in a Singleton class:
private static readonly object SyncObject = new object();
public static MySingleton Instance
{
get
{
lock (SyncObject)
{
if (_instance == null)
{
_instance = new MySingleton();
}
}
return _instance;
}
}
public int MyMethod()
{
lock (SyncObject)
{
// Read or write
}
}
Will this cause issues?
If the methods are unrelated as you state, then use a different lock for each one; otherwise it's inefficient (since there's no reason for different methods to lock on the same object, as they could safely execute concurrently).
Also, it seems that these are instance methods locking on a static object -- was that intended? I have a feeling that's a bug; instance methods should (usually) only lock on instance fields.
Regarding the Singleton design pattern:
While locking can be safe for those, better practice is doing a delayed initialization of a field like this:
private static object sharedInstance;
public static object SharedInstance
{
get
{
if (sharedInstance == null)
Interlocked.CompareExchange(ref sharedInstance, new object(), null);
return sharedInstance;
}
}
This way it's a little bit faster (both because interlocked methods are faster, and because the initialization is delayed), but still thread-safe.
By using the same object to lock on in all of those methods, you are serializing all access to code in all of the threads.
That is... code running GetValue1() will block other code in a different thread from running GetValue2() until it's done. If you add even more code that locks on the same object instance, you'll end up with effectively a single-threaded application at some point.
Shared lock locks other non-related calls
If you use the same lock then locking in one method unnecessarily locks others as well. If they're not related at all than this is a problem since they have to wait for each other. Which they shouldn't.
Bottleneck
This may pose a bottleneck when these methods are frequently called. With separate locks they would run independently, but sharing the same lock it means they must wait for the lock to be released more often as required (actually three times more often).
To create a thread-safe singleton, use this technique.
You don't need a lock.
In general, each lock should be used as little as possible.
The more methods lock on the same thing, the mroe likely you are to end up waiting for it when you don't really need to.
Good question. There are pros and cons of making locks more fine grained vs more coarse grained, with one extreme being a separate lock for each piece of data and the other extreme being one lock for the entire program. As other posts point out, the disadvantage of reusing the same locks is in general you may get less concurrency (though it depends on the case, you may not get less concurrency).
However, the disadvantage of using more locks is in general you make deadlock more likely. There are more ways to get deadlocks the more locks you have involved. For example, acquiring two locks at the same time in separate threads but in the opposite order is a potential deadlock which wouldn't happen if only one lock were involved. Of course sometimes you may fix a deadlock by breaking one lock into two, but usually fewer locks means fewer deadlocks. There's also added code complexity of having more locks.
In general these two factors need to be balanced. It's common to use one lock per class for convenience if it doesn't cause any concurrency issues. In fact, doing so is a design pattern called a monitor.
I would say the best practice is to favor fewer locks for code simplicity's sake and make additional locks if there's a good reason (such as concurrency, or a case where it's more simple or fixes a deadlock).
I have a method which should be executed in an exclusive fashion. Basically, it's a multi threaded application where the method is invoked periodically by a timer, but which could also be manually triggered by a user action.
Let's take an example :
The timer elapses, so the method is
called. The task could take a few
seconds.
Right after, the user clicks on some
button, which should trigger the
same task : BAM. It does nothing
since the method is already running.
I used the following solution :
public void DoRecurentJob()
{
if(!Monitor.TryEnter(this.lockObject))
{
return;
}
try
{
// Do work
}
finally
{
Monitor.Exit(this.lockObject);
}
}
Where lockObject is declared like that:
private readonly object lockObject = new object();
Edit : There will be only one instance of the object which holds this method, so I updated the lock object to be non-static.
Is there a better way to do that ? Or maybe this one is just wrong for any reason ?
This looks reasonable if you are just interested in not having the method run in parallel. There's nothing to stop it from running immediately after each other, say that you pushed the button half a microsecond after the timer executed the Monitor.Exit().
And having the lock object as readonly static also make sense.
You could also use Mutex or Semaphore if you want it to work cross process (with a slight performance penalty), or if you need to set any other number than one of allowed simultaneous threads running your piece of code.
There are other signalling constructs that would work, but your example looks like it does the trick, and in a simple and straightforward manner.
Minor nit: if the lockObject variable is static, then "this.lockObject" shouldn't compile. It also feels slightly odd (and should at least be heavily documented) that although this is an instance method, it has distinctly type-wide behaviour as well. Possibly make it a static method which takes an instance as the parameter?
Does it actually use the instance data? If not, make it static. If it does, you should at least return a boolean to say whether or not you did the work with the instance - I find it hard to imagine a situation where I want some work done with a particular piece of data, but I don't care if that work isn't performed because some similar work was being performed with a different piece of data.
I think it should work, but it does feel a little odd. I'm not generally a fan of using manual locking, just because it's so easy to get wrong - but this does look okay. (You need to consider asynchronous exceptions between the "if" and the "try" but I suspect they won't be a problem - I can't remember the exact guarantees made by the CLR.)
I think Microsoft recommends using the lock statement, instead of using the Monitor class directly. It gives a cleaner layout and ensures the lock is released in all circumstances.
public class MyClass
{
// Used as a lock context
private readonly object myLock = new object();
public void DoSomeWork()
{
lock (myLock)
{
// Critical code section
}
}
}
If your application requires the lock to span all instances of MyClass you can define the lock context as a static field:
private static readonly object myLock = new object();
The code is fine, but would agree with changing the method to be static as it conveys intention better. It feels odd that all instances of a class have a method between them that runs synchronously, yet that method isn't static.
Remember you can always have the static syncronous method to be protected or private, leaving it visible only to the instances of the class.
public class MyClass
{
public void AccessResource()
{
OneAtATime(this);
}
private static void OneAtATime(MyClass instance)
{
if( !Monitor.TryEnter(lockObject) )
// ...
This is a good solution although I'm not really happy with the static lock. Right now you're not waiting for the lock so you won't get into trouble with deadlocks. But making locks too visible can easily get you in to trouble the next time you have to edit this code. Also this isn't a very scalable solution.
I usually try to make all the resources I try to protect from being accessed by multiple threads private instance variables of a class and then have a lock as a private instance variable too. That way you can instantiate multiple objects if you need to scale.
A more declarative way of doing this is using the MethodImplOptions.Synchronized specifier on the method to which you wish to synchronize access:
[MethodImpl(MethodImplOptions.Synchronized)]
public void OneAtATime() { }
However, this method is discouraged for several reasons, most of which can be found here and here. I'm posting this so you won't feel tempted to use it. In Java, synchronized is a keyword, so it may come up when reviewing threading patterns.
We have a similar requirement, with the added requirement that if the long-running process is requested again, it should enqueue to perform another cycle after the current cycle is complete. It's similar to this:
https://codereview.stackexchange.com/questions/16150/singleton-task-running-using-tasks-await-peer-review-challenge
private queued = false;
private running = false;
private object thislock = new object();
void Enqueue() {
queued = true;
while (Dequeue()) {
try {
// do work
} finally {
running = false;
}
}
}
bool Dequeue() {
lock (thislock) {
if (running || !queued) {
return false;
}
else
{
queued = false;
running = true;
return true;
}
}
}