Freigeben über


Threading deep dive – Day 8

Volatile Read / Writes

 MSDN says "The volatile modifier is usually used for a field that is accessed by multiple threads without using the lock statement to serialize access. Using the volatile modifier ensures that one thread retrieves the most up-to-date value written by another thread. " And refer C# language specification for volatile field. Now you might have good idea on what is happening when Volatile read / writes are performed. Yes. You are right. Volatile keyword tells the compiler to not to optimize the field. So that instruction reordering will not happen for reads and writes of volatile field. Volatile fields simply guarantees that the sequence of writes and reads of values would be performed as specified in the code. JIT optimization does not affect volatile fields. We can also say volatile always makes the read happening from the RAM

 Interlocked vs Volatile.

Volatile fields only mandate sequence. Not atomicity. We may not get up-to-date value if we use volatile as they are not atomic. Between volatile read and volatile write, the data processing thread may get preempted and the value in the RAM may get updated by other threads [from other processors]. When the thread in question gets the processor time, it would continue process the old value as the value from the RAM is different from the time it is read.

 One should consider using Volatile on following criteria

1. Value need not to be very recent.

2. JIT optimization is not required as the instruction reordering may disturb the business logic.

 

I would suggest you the following link to go through to have good Idea on the difference between Atomic operation and Volatile keyword.

https://forums.msdn.microsoft.com/en-US/clr/thread/ec656080-7521-4f61-8df3-d7168da5cf4c

Memory Barriers

Instructions re-ordering happen at two levels. 1. A the compiler level which can be controlled with Volatile keyword. By including Volatile keyword we instruct the compiler, not to optimize the code by re-ordering the instructions. 2. Second level of reordering happens at the processor level. Memory barrier is the way to tell the underlying hardware to skip any reordering that happens at the hardware level.

 Interestingly Thread.VolatilRead and Thread.VolatileWrite use memory barriers internally. Below is the reflected code snippet for Thread.VolatileRead and VolatileWrite for Int32 overloads

 [MethodImpl(MethodImplOptions.NoInlining)]
public static int VolatileRead(ref int address)
{
int num = address;
MemoryBarrier();
return num;
}

For Thread.VolatileWrite

[MethodImpl(MethodImplOptions.NoInlining)]
public static void VolatileWrite(ref int address, int value)
{
MemoryBarrier();
address = value;
}

 Ok. Now I have set of questions for you.

1.Can you write atomic functions on your own?

2.Can I some how avoid thread pre-emption?

3.Who will preempt windows scheduler?

4.I know about pre-emption. What is interruption?

5.What is Acquire and Release from Memory barrier?

 For answers, refer below the links:

 https://download.microsoft.com/download/e/b/a/eba1050f-a31d-436b-9281-92cdfeae4b45/Locks.doc

 https://download.microsoft.com/download/e/b/a/eba1050f-a31d-436b-9281-92cdfeae4b45/IRQL_thread.doc

 These are must read links that gives in-depth knowledge on Memory barrier, Atomicity, Locking and Thread IRQL etc.

Processor affinity

On a multi-processor environment, a thread can run on any processor whenever the thread gets switched. The OS scheduler decides on assigning different thread to different processor. There is no guarantee that the a particular thread will always run on a particular processor. We can confine a thread to run on a particular processor. This is what called setting processor affinity to a thread. Unless there is a compelling reason , one should not set processor affinity to a thread. Setting processor affinity to a thread is not good for your program performance. Setting processor affinity through code may lead to under utilizing some of the processors. ProcessThread class lets you assign affinity to one processor to a thread. Here you have to enumerate through all the threads from the process to get hold of ProcessThread. We cannot create Process Thread as this class does not have any constructor or singleton supporting static methods. If I'm not wrong we have to use Native Thread ID to match a Thread and ProcessThread.

 

What is the current thread means on a multi processor environment?

A process running on a multi-processor environment may have more than one thread. In that case which thread would be represented by Thread.CurrentThread property? This property always return the object of the thread that is currently executing that statement. Do not assume a process will have only one current thread at any point in time in multi-processor environment.

 

Lock convoy?

Think about this situation. Many threads are waiting for a lock. But no one owns the lock. This is kind of situation is called lock convoy. Interesting. Read more from the below link. https://blogs.msdn.com/larryosterman/archive/2004/03/29/101329.aspx

Comments