Lock actually is the short for Monitor.Enter and Monitor.Exit
Here is the code
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
new Thread(Go).Start();
}
Thread.Sleep(1000);
Console.Read();
}
static int val1 = 90, val2 = 10;
static object locker = new object();
static void Go()
{
lock (locker)
{
if (val2 != 0)
{
Thread.Sleep(20);
Console.WriteLine(val1 / val2);
val2 = 0;
}
else
{
Console.WriteLine("attempted to divide by zero");
}
}
}
}
lets look what happens when you start 100 threads of Go function starts and if you don’t lock gives a attempted to divide by zero exception.When you lock problem is solved, lets look at the il code:
.method private hidebysig static void Go() cil managed
{
// Code size 88 (0x58)
.maxstack 2
.locals init ([0] object CS$2$0000,
[1] bool CS$4$0001)
IL_0000: nop
IL_0001: ldsfld object ConsoleApplication12.Program::locker
IL_0006: dup
IL_0007: stloc.0
IL_0008: call void [mscorlib]System.Threading.Monitor::Enter(object)
IL_000d: nop
.try
{
IL_000e: nop
IL_000f: ldsfld int32 ConsoleApplication12.Program::val2
IL_0014: ldc.i4.0
IL_0015: ceq
IL_0017: stloc.1
IL_0018: ldloc.1
IL_0019: brtrue.s IL_003e
IL_001b: nop
IL_001c: ldc.i4.s 20
IL_001e: call void [mscorlib]System.Threading.Thread::Sleep(int32)
IL_0023: nop
IL_0024: ldsfld int32 ConsoleApplication12.Program::val1
IL_0029: ldsfld int32 ConsoleApplication12.Program::val2
IL_002e: div
IL_002f: call void [mscorlib]System.Console::WriteLine(int32)
IL_0034: nop
IL_0035: ldc.i4.0
IL_0036: stsfld int32 ConsoleApplication12.Program::val2
IL_003b: nop
IL_003c: br.s IL_004b
IL_003e: nop
IL_003f: ldstr "attempted to divide by zero"
IL_0044: call void [mscorlib]System.Console::WriteLine(string)
IL_0049: nop
IL_004a: nop
IL_004b: nop
IL_004c: leave.s IL_0056
} // end .try
finally
{
IL_004e: ldloc.0
IL_004f: call void [mscorlib]System.Threading.Monitor::Exit(object)
IL_0054: nop
IL_0055: endfinally
} // end handler
IL_0056: nop
IL_0057: ret
} // end of method Program::Go
As you can see it is a try finally block and monitor.enter and monitor.exit methods.If you replace lock with monitor codes given below il code will be same
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
new Thread(Go).Start();
}
Thread.Sleep(1000);
Console.Read();
}
static int val1 = 90, val2 = 10;
static object locker = new object();
static void Go()
{
Monitor.Enter(locker);
try
{
if (val2 != 0)
{
Thread.Sleep(20);
Console.WriteLine(val1 / val2);
val2 = 0;
}
else
{
Console.WriteLine("attempted to divide by zero");
}
}
finally
{
Monitor.Exit(locker);
}
}
}
lock(this) is not a good programming example i will tell more about it another time but for now don’t use it. You must lock a reference variable (please remember structs are value and classes are reference types),
No comments:
Post a Comment