It is generally accepted (I believe!) that a lock will force any values from fields to be reloaded (essentially acting as a memory-barrier or fence - my terminology in this area gets a bit loose, I'm afraid), with the consequence that fields that are only ever accessed inside a lock do not themselves need to be volatile.
(If I'm wrong already, just say!)
A good comment was raised here, questioning whether the same is true if code does a Wait() - i.e. once it has been Pulse()d, will it reload fields from memory, or could they be in a register (etc).
Or more simply: does the field need to be volatile to ensure that the current value is obtained when resuming after a Wait()?
Looking at reflector, Wait calls down into ObjWait, which is managed internalcall (the same as Enter).
The scenario in question was:
bool closing;
public bool TryDequeue(out T value) {
lock (queue) { // arbitrary lock-object (a private readonly ref-type)
while (queue.Count == 0) {
if (closing) { // <==== (2) access field here
value = default(T);
return false;
}
Monitor.Wait(queue); // <==== (1) waits here
}
...blah do something with the head of the queue
}
}
Obviously I could just make it volatile, or I could move this out so that I exit and re-enter the Monitor every time it gets pulsed, but I'm intrigued to know if either is necessary.
Since the Wait() method is releasing and reacquiring the Monitor lock, if lock performs the memory fence semantics, then Monitor.Wait() will as well.
To hopefully address your comment:
The locking behavior of Monitor.Wait() is in the docs (http://msdn.microsoft.com/en-us/library/aa332339.aspx), emphasis added:
When a thread calls Wait, it releases the lock on the object and enters the object's waiting queue. The next thread in the object's ready queue (if there is one) acquires the lock and has exclusive use of the object. All threads that call Wait remain in the waiting queue until they receive a signal from Pulse or PulseAll, sent by the owner of the lock. If Pulse is sent, only the thread at the head of the waiting queue is affected. If PulseAll is sent, all threads that are waiting for the object are affected. When the signal is received, one or more threads leave the waiting queue and enter the ready queue. A thread in the ready queue is permitted to reacquire the lock.
This method returns when the calling thread reacquires the lock on the object.
If you're asking about a reference for whether a lock/acquired Monitor implies a memory barrier, the ECMA CLI spec says the following:
12.6.5 Locks and Threads:
Acquiring a lock (System.Threading.Monitor.Enter or entering a synchronized method) shall implicitly perform a volatile read operation, and releasing a lock (System.Threading.Monitor.Exit or leaving a synchronized method) shall implicitly perform a volatile write operation. See §12.6.7.
12.6.7 Volatile Reads and Writes:
A volatile read has "acquire semantics" meaning that the read is guaranteed to occur prior to any references to memory that occur after the read instruction in the CIL instruction sequence. A volatile write has "release semantics" meaning that the write is guaranteed to happen after any memory references prior to the write instruction in the CIL instruction sequence.
Also, these blog entries have some details that might be of interest:
http://blogs.msdn.com/jaredpar/archive/2008/01/17/clr-memory-model.aspx
http://msdn.microsoft.com/msdnmag/issues/05/10/MemoryModels/
http://www.bluebytesoftware.com/blog/2007/11/10/CLR20MemoryModel.aspx
Further to Michael Burr's answer, not only does Wait release and re-acquire the lock, but it does this so that another thread can take out the lock in order to examine the shared state and call Pulse. If the second thread doesn't take out the lock then Pulse will throw. If they don't Pulse the first thread's Wait won't return. Hence any other thread's access to the shared state must happen within a proper memory-barried scenario.
So assuming the Monitor methods are being used according to the locally-checkable rules, then all memory accesses happen inside a lock, and hence only the automatic memory barrier support of lock is relevant/necessary.
Maybe I can help you this time... instead of using a volatile you can use Interlocked.Exchange with an integer.
if (closing==1) { // <==== (2) access field here
value = default(T);
return false;
}
// somewhere else in your code:
Interlocked.Exchange(ref closing, 1);
Interlocked.Exchange is a synchronization mechanism, volatile isn't... I hope that's worth something (but you probably already thought about this).
Related
I have a C# program, where I'm spawning a thread to do some calculations. I'm then adding the result of the calculations to a Queue, and from the main thread, I'm constantly checking to see if the Queue has length more than 0. If it does, then the result of the calculation is de-queued and used elsewhere.
I've read that I should lock the queue when accessing it from either thread because it may cause problems if both threads are accessing it at the same time. But should I lock it whenever I do ANYTHING with the Queue, or only when en-queuing/de-queuing?
E.g.
// In main thread
lock (meshDataQueue) {
if (meshDataQueue.Count > 0)
{
constructMesh(meshDataQueue.dequeue())
}
}
vs.
if (meshDataQueue.Count > 0) {
lock (meshDataQueue)
{
constructMesh(meshDataQueue.dequeue())
}
}
Yes, you should lock the Queue instance (using always the same "locker" object) whenever you do anything with it, including trivial things like reading the queue's Count. The Queue class is not thread-safe, so for its behavior to stay defined you must ensure that it is accessed by one thread at a time (with proper memory barriers when switching from thread to thread, that the lock statement robustly provides). Otherwise you enter the undefined behavior territory, where all guarantees are off.
Consider two threads run simultaneously. A is reading and B is writing. When A is reading, in the middle of code ,CPU time for A finishes then B thread continues.
Is there any way to don't give back CPU until A finishes, but B can start or continue?
You need to understand that you have almost no control over when CPU is given back and to whom it is given. The operating system does that. To have control on that, you'd need to be the operating system. The only things you can usually do are:
start a thread
set thread priority, so some threads are may more likely get time than others
put a thread to sleep, immediatelly and ask the operating system to wake it up upon some condition, maybe with some timeout (waiting time limit)
as a special case, or a typical use case, the second point is often also provided with a shorthand:
put a thread to sleep, immediatelly for a specified amount of time
By "sleep" I mean that this thread is paused and will not get any CPU time, even if all CPUs are idle, unless the thread is woken up by the OS due to some condition.
Furthermore, in a typical case, there is no "thread A and thread B that switch CPU time between them", but there is "lots of threads from various processes and the operating system itself, and you two threads". This means that when your thread A loses the CPU, most probably it will not be the thread B that gets the time now. Some other thread from somewhere else will get it, and at some future point of time, maybe your thread A or maybe thread B will get it back.
This means that there is very little you can be sure. You can be sure that your threads are
either dead
or sleeping
or proceeding 'forward' in a hard to determine order
If you need to ensure that some threads are synchronized, you must .. not start them simultaneously, or put them sleep in precise moments and wake them up in precise order.
You've just said in comments:
You know, if in the middle of A CPU time finishes, data that has been retrieved is not complete
This means that you need to ensure that thread B does not try to touch the data before thread A finishes writing it. But also, if you think about it, you need to ensure that thread A doesn't start writing next data if the thread B is now reading previous data.
This means synchronization. This means that threads A and B must wait if the other thread is touching the data. This means that they need to be put to sleep and woken up when the other thread finishes.
In C#, the easiest way to do that is to use lock(x) keyword. When a thread enters a lock() section, it proceeds only if it is able to get the lock. If not, it is put to sleep. It can't get the lock if any other thread was faster and got it before. However, a thread releases the lock when it ends its job. Upon that time, one of the sleeping threads is woken up and given the lock.
lock(fooo) { // <- this line means 'acquire the lock or sleep'
iam.doing(myjob);
very.important(things);
thatshouldnt.be.interrupted();
byother(threads);
} // <- this line means 'release the lock'
So, when a thread gets through the lock(fooo){ line, you can't be sure it won't be interrupted. Oh, surely it will be. OS will switch the threads back and forth to other processes, and so on. But you can be sure that no other threads of your app will be inside the code block. If they tried to get inside while your thread got that lock, they'd imediatelly fall asleep in the first lock line. One of them be will be later woken up when your thread gets out of that code.
There's one more thing. lock() keyword requires a parameter. I wrote foo there. You need to pass there something that will act as the lock. It can be any object, even plain object:
private object thelock = new object();
private void dosomething()
{
lock(thelock)
{
foobarize(thebaz);
}
}
however you must ensure that all threads try to use the same lock instance. Writing a code like
private void dosomething()
{
object thelock = new object();
lock(thelock)
{
foobarize(thebaz);
}
}
is a nonsense since every potential thread executing that lines will try lockin upon their own new object instance and will see it as "free" (it's new, just created, noone took it earlier) and will immediatelly get into the protected code block.
Now you wrote about using ConcurrentQueue. This class provides safely mechanisms against concurrency. You can be sure that adding or reading or removing items from that queue is already safe. This collection makes it safe. You don't need to add synchronization to add or remove items safely. It's safe. If you observe any ill effects, then most probably you have tried putting an item into that collection and then you were modifying that item. Concurrent collection will not guard you against that. It can only make sure that add/remove/etc are safe. But it has no knowledge or control on what you do to the items:
In short, if some thread B tries to read items from the collection, then in thread A this is NOT safe:
concurrentcoll.Add(item);
item.x = 5;
item.foobarize();
but this is safe:
item.x = 5;
item.foobarize();
concurrentcoll.Add(item);
// and do not touch the Item anymore here.
When you look at C#'s Monitor class, the one used under the hood of the lock keyword, you'll find that in its implementation you have a condition variable and a mutex. The mutex is acquired by a new thread entering, if not already acquired by another thread, and then it goes on to check the condition variable, if it is true, the thread can proceed, if it isn't true, then it gets put on the condition variable's thread sleep queue, in order to be woken when the condition variable becomes true again.
Now, why does Monitor need a condition variable? What condition does it check? I have read through wikipedia's article on Monitor and I haven't been able to deduce what condition it would wait on?
Its not something specified by the user of lock or Monitor, but some internal variable. Seeing that the object taking as argument by lock, is supposedly only for identifying the lock.
Is this just like using a AutoResetEvent and a Mutex and acquiring a lock on the Mutex and then seeing if the AutoResetEvent is set to signalled?
I'm not sure I get why Monitor needs a condition variable, when a thread waits to acquire a mutex, doesn't it also get woken up when the mutex is released? (The OS scheduler being the one that probably does the waking)
I'm hoping that this makes sense, and that someone can find the gap in my understanding.
This is an overload of the Monitor.Enter method introduced in CLR 4.0 to correct a subtle vulnerability.
This is explained in this website.
Monitor.Enter (_locker);
try
{
if (_val2 != 0) Console.WriteLine (_val1 / _val2);
_val2 = 0;
}
finally { Monitor.Exit (_locker); }
Consider the (unlikely) event of an exception being thrown within the implementation of Monitor.Enter, or between the call to Monitor.Enter and the try block (due, perhaps, to Abort being called on that thread — or an OutOfMemoryException being thrown). In such a scenario, the lock may or may not be taken. If the lock is taken, it won’t be released — because we’ll never enter the try/finally block. This will result in a leaked lock.
To avoid this danger, CLR 4.0’s designers added the following overload to Monitor.Enter
Currently, I'm learning for a multithreading exam. I read the good threading article of albahari. I've got a question at the monitor usage - why is here used a loop in place of an if?
lock (_locker)
{
while (!_go) //why while and not if?
Monitor.Wait (_locker); // _lock is released
// lock is regained
...
}
I think, that an if would be sufficient.
I'm afraid, that I don't understand the article completely.
//Edit
Example-Code:
class SimpleWaitPulse
{
static readonly object _locker = new object();
static bool _go;
static void Main()
{ // The new thread will block
new Thread (Work).Start(); // because _go==false.
Console.ReadLine(); // Wait for user to hit Enter
lock (_locker) // Let's now wake up the thread by
{ // setting _go=true and pulsing.
_go = true;
Monitor.Pulse (_locker);
}
}
static void Work()
{
lock (_locker)
while (!_go)
Monitor.Wait (_locker); // Lock is released while we’re waiting
Console.WriteLine ("Woken!!!");
}
}
It just depends on the situation. In this case the code is just waiting for _go to be true.
Every time _locker is pulsed it will check to see if _go has been set to true. If _go is still false, it will wait for the next pulse.
If an if was used instead of a while, it would only wait once (or not at all if _go was already true), and would then continue on after a pulse, regardless of the new state of _go.
So how you use Monitor.Wait() depends entirely on your specific needs.
It really just depends on the situation. But first, we need to clarify how Monitors work. When a thread proceeds to signal a thread through Monitor.Pulse(), there is usually no guarantee that the signaled thread will actually run next. This means that it is possible for other threads to run before the signaled thread and change the condition under which it was okay for the signaled thread to proceed. This means that the signaled thread still needs to check if is safe for it to proceed after being woken up (ie the while loop). However, certain rare synchronization problems allow you to make the assumption that once a thread has been signaled to wake up (ie Monitor.Pulse()), no other thread has the ability to change the condition under which it is safe to proceed (ie. the if condition).
I wrote an article that might help here: Wait and Pulse demystified
There's more going on than is immediately obvious.
I've got a question at the monitor usage - why is here used a loop in
place of an if?
There is a well known rule when working with Pulse and Wait that states that when in doubt prefer while over an if. Clearly, either one will work in this case, but in almost every other situation while is required. In fact, there are very few (if any) scenarios where using a while loop would produce an incorrect result. That is the basis for this general rule. The author used a while loop because he was trying to stick with the tried-and-true pattern. He even provides the template in the same article. Here is it is:
lock (_locker)
while ( <blocking-condition> )
Monitor.Wait (_locker);
The simplest way to write correct code with Monitor.Wait is to assume the system will regard it as "advisory", and assume that the system may arbitrarily wake any waiting thread any time it can acquire the lock, without regard for whether Pulse has been called. The system usually won't do so, of course, but if a program is using Wait and Pulse properly, its correctness should not be affected by having Wait calls arbitrarily exit early for no reason. Essentially, one should regard Wait as a means of telling the system "Continuing execution past here will be a waste of time unless or until someone else calls Pulse".
I have developed a generic producer-consumer queue which pulses by Monitor in the following way:
the enqueue :
public void EnqueueTask(T task)
{
_workerQueue.Enqueue(task);
Monitor.Pulse(_locker);
}
the dequeue:
private T Dequeue()
{
T dequeueItem;
if (_workerQueue.Count > 0)
{
_workerQueue.TryDequeue(out dequeueItem);
if(dequeueItem!=null)
return dequeueItem;
}
while (_workerQueue.Count == 0)
{
Monitor.Wait(_locker);
}
_workerQueue.TryDequeue(out dequeueItem);
return dequeueItem;
}
the wait section produces the following SynchronizationLockException :
"object synchronization method was called from an unsynchronized block of code"
do i need to synch it? why ? Is it better to use ManualResetEvents or the Slim version of .NET 4.0?
Yes, the current thread needs to "own" the monitor in order to call either Wait or Pulse, as documented. (So you'll need to lock for Pulse as well.) I don't know the details for why it's required, but it's the same in Java. I've usually found I'd want to do that anyway though, to make the calling code clean.
Note that Wait releases the monitor itself, then waits for the Pulse, then reacquires the monitor before returning.
As for using ManualResetEvent or AutoResetEvent instead - you could, but personally I prefer using the Monitor methods unless I need some of the other features of wait handles (such as atomically waiting for any/all of multiple handles).
From the MSDN description of Monitor.Wait():
Releases the lock on an object and blocks the current thread until it reacquires the lock.
The 'releases the lock' part is the problem, the object isn't locked. You are treating the _locker object as though it is a WaitHandle. Doing your own locking design that's provably correct is a form of black magic that's best left to our medicine man, Jeffrey Richter and Joe Duffy. But I'll give this one a shot:
public class BlockingQueue<T> {
private Queue<T> queue = new Queue<T>();
public void Enqueue(T obj) {
lock (queue) {
queue.Enqueue(obj);
Monitor.Pulse(queue);
}
}
public T Dequeue() {
T obj;
lock (queue) {
while (queue.Count == 0) {
Monitor.Wait(queue);
}
obj = queue.Dequeue();
}
return obj;
}
}
In most any practical producer/consumer scenario you will want to throttle the producer so it cannot fill the queue unbounded. Check Duffy's BoundedBuffer design for an example. If you can afford to move to .NET 4.0 then you definitely want to take advantage of its ConcurrentQueue class, it has lots more black magic with low-overhead locking and spin-waiting.
The proper way to view Monitor.Wait and Monitor.Pulse/PulseAll is not as providing a means of waiting, but rather (for Wait) as a means of letting the system know that the code is in a waiting loop which can't exit until something of interest changes, and (for Pulse/PulseAll) as a means of letting the system know that code has just changed something that might cause satisfy the exit condition some other thread's waiting loop. One should be able to replace all occurrences of Wait with Sleep(0) and still have code work correctly (even if much less efficiently, as a result of spending CPU time repeatedly testing conditions that haven't changed).
For this mechanism to work, it is necessary to avoid the possibility of the following sequence:
The code in the wait loop tests the condition when it isn't satisfied.
The code in another thread changes the condition so that it is satisfied.
The code in that other thread pulses the lock (which nobody is yet waiting on).
The code in the wait loop performs a Wait since its condition wasn't satisfied.
The Wait method requires that the waiting thread have a lock, since that's the only way it can be sure that the condition it's waiting upon won't change between the time it's tested and the time the code performs the Wait. The Pulse method requires a lock because that's the only way it can be sure that if another thread has "committed" itself to performing a Wait, the Pulse won't occur until after the other thread actually does so. Note that using Wait within a lock doesn't guarantee that it's being used correctly, but there's no way that using Wait outside a lock could possibly be correct.
The Wait/Pulse design actually works reasonably well if both sides cooperate. The biggest weaknesses of the design, IMHO, are (1) there's no mechanism for a thread to wait until any of a number of objects is pulsed; (2) even if one is "shutting down" an object such that all future wait loops should exit immediately (probably by checking an exit flag), the only way to ensure that any Wait to which a thread has committed itself will get a Pulse is to acquire the lock, possibly waiting indefinitely for it to become available.