Thanks in advance,
Arnab
> Can anyone tell me how these locks/monitors are
> typically and efficiently compiled?
If you look at the .NET languages you will find that this "languages
features" are typically implemented as calls to methods.
The 'lock' feature on c# is implemented via calls to the Monitor class.
For instance, the following c# fragment
private static void Main(string[] args)
{
object obj = new object();
lock (obj)
{
}
}
is compiled to the following IL
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 2
.locals init (
[0] object obj,
[1] object CS$2$0000)
L_0000: nop
L_0001: newobj instance void [mscorlib]System.Object::.ctor()
L_0006: stloc.0
L_0007: ldloc.0
L_0008: dup
L_0009: stloc.1
L_000a: call void [mscorlib]System.Threading.Monitor::Enter(object)
L_000f: nop
L_0010: nop
L_0011: nop
L_0012: leave.s L_001c
L_0014: ldloc.1
L_0015: call void [mscorlib]System.Threading.Monitor::Exit(object)
L_001a: nop
L_001b: endfinally
L_001c: nop
L_001d: ret
.try L_0010 to L_0014 finally handler L_0014 to L_001c
}
Normally this "features" are implemented by classes which wrap O.S.
objects that do the hard work.
> Can you cite any paper on this?
No, don't know papers to recommend on this matter.
HTH,
Felipe
Hi Arnab,
for Java the papers you should look at are on thin locking [1] and
then on lock reservation/biasing [2][3]. A thin lock is a word in an
object that you assume will show that an object is not locked and then
you try to swap in your thread ID, if your compare and swap found a
non-zero value you have contention and then you need a fat lock (a
separate data structure). On releasing the thin lock you do a compare
and swap and if your thread ID has been changed to a fat lock
reference then you need to go to the fat lock to wake up a contending
thread. Lock reservation changes this so that on the release you do no
work (no CAS), instead contending threads add themselves to a list of
contending threads paired with objects that when crossing a safepoint
are processed. With reservation an object is often owned by your
thread (biased to it or reserved by it) and to check the thread still
owns the lock you don't need a full CAS, just a load (hence locking
with no atomic operations). In Java locks can be held recursively,
adding complexity. You also may not want lock reservation/biasing in
some performance scenarios, and you may want to busy wait in some
scenarios too.
Regards,
Ian Rogers
[1] http://www.research.ibm.com/people/d/dfb/thinlocks.html
[2] http://doi.acm.org/10.1145/582419.582433 - Lock reservation: Java
locks can mostly do without atomic operations
[3]
http://java.sun.com/javase/technologies/hotspot/publications/biasedlocking_oo
psla2006_wp.pdf
In the Windows API there are CriticalSection objects:
http://msdn.microsoft.com/en-us/library/ms682530%28VS.85%29.aspx
and Mutex objects:
http://msdn.microsoft.com/en-us/library/ms684266%28VS.85%29.aspx
Under the POSIX API (implemented by NPTL under Linux) there are
mutexs:
https://computing.llnl.gov/tutorials/pthreads/#MutexOverview
I think maybe that the locks provided by Java and C# are just wrappers
for these system calls. I am not 100% sure though.
Regards,
Andrew.
--
Andrew Tomazos <and...@tomazos.com> <http://www.tomazos.com>