Memory barriers, etc.

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Certainly it is clear when not using locking constructs if you don't use a
volatile keyword for variable access and you loop on the variable and check
it's value, you may be looking at the register value and not the actual value
so it may never change. The question is, is it possible even with locking
constructs this is an issue.

ALso, what locking constructs will force a memory barrier to prevent
enregistration of a variable? Any of them such as lock, Monitor enter/exit,
WaitOne, Set on events etc?



Will the JIT possibly possibly register the variable so that we would not
see it’s value change in some circumstances? Even in cases where locking IS
used?



If for example you had something like the code below. Imagine each of these
methods was started on a separate thread.


Public class Myclass()

{

private Int my_value=0;



Public void Mythread1Func()

{

While (true)

{

Monitor.Enter(this);

my_value++; //I presume that writes will always happen even
if this did get put into a register?

Monitor.Exit(this);

}



}



Public void MyThread2Func()

{



Monitor.Enter(this);

While(my_value<500000) // Would the JIT have possibly
put my_value in a register so we never see it change?

{

Monitor.Exit(this);



Monitor.Enter(this);



}



Monitor.Exit(this);



}



//This example would make it harder for the compiler and JIT to
determine what is going on, would this be a problem

Public void MyThread3Func()

{

While (true)

{



Utils.Lock(this);

Int value=my_value; // could my_value be put in a register here
and then when we access it later it has actually not been updated?

Utils.Unlock(this);



Utils.Lock(this);

If (my_value>500000) // Would the JIT have possibly
put my_value in a register so we never see it change?



{

Utils.Unlock(this);
break;

}

Utils.Unlock(this);

}



}

}



Public class Utils

{

Public static void Lock(object obj)

{

Monitor.Enter(obj);

}



Public static void Unlock(object obj)

{

Monitor.Exit(obj);

}



}
 
WXS said:
Certainly it is clear when not using locking constructs if you don't
use a volatile keyword for variable access and you loop on the
variable and check it's value, you may be looking at the register
value and not the actual value so it may never change. The question
is, is it possible even with locking constructs this is an issue.

No. Monitor.Enter and Monitor.Exit have volatile read and write
semantics. Acquiring a lock will create a read memory barrier and
releasing the lock will create a write memory barrier.
ALso, what locking constructs will force a memory barrier to
prevent enregistration of a variable? Any of them such as lock,
Monitor enter/exit, WaitOne, Set on events etc?

The important word in your question is 'prevent'. The volatile keyword
is the only one I know of that will actually *prevent* the caching of a
variable. A variable could still be cached inside a critical section,
but it will be read from memory upon acquiring the lock and written to
memory upon releasing the lock.

The Monitor and Interlocked classes create memory barriers. Some
methods on the Thread class do as well including Thread.VolatileRead,
Thread.VolatileWrite, and Thread.MemoryBarrier.
Will the JIT possibly possibly register the variable so that we
would not see it's value change in some circumstances?

Only if the synchronization were not done correctly. Even when done
incorrectly you'll have a difficult time trying to reproduce a problem
on most hardware and framework version combinations. The important
thing is that circumstances do exist.
Even in cases where locking IS used?

No. The specification guarentees there will not be a problem if
locking is used correctly.

Brian
 
Back
Top