0%

Monitor和Lock区别

Lock和Monitor没区别,简单来讲Lock是Monitor的进一步封装
锁定的目的:由于多个线程并行/并发处理同一个“数据对象”(比如:在其它线程的某个地方发生了Clear、Add、Remove、Change等操作),导致“数据对象”不断变化,没法用了,所以,为了保证数据在某个计算时刻的“恒定”,使用排它锁将“数据对象”锁定,然后就视该“数据对象”为“一个恒定量”进行逻辑处理。

1.代码使用

Lock Monitor
Lock(obj)
{
执行任务
}
Monitor.Enter(obj);
try{
执行任务
}finally
{
Monitor.Exit(obj);
}

2.Example

  • 使用Task.WaitAll 等待子线程完成
  • Monitor琐死要变化的参数,使其在使用时无法突变
  • 使用Stopwatch观察子线程执行时长
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
static void Main()
{

Console.WriteLine("Monitor Demo ...");

int nTasks = 0;
object obj = nTasks;

List<Task> tasks = new List<Task>();

try
{
Console.WriteLine($"nTasks:{nTasks};MainThreadId:{Thread.CurrentThread.ManagedThreadId}");
Stopwatch sw = new Stopwatch();
sw.Start();

for (int ctr=0;ctr<10;ctr++)
{
tasks.Add(Task.Run(async() => {
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine($"子任务{Thread.CurrentThread.ManagedThreadId} 延时5000ms");
await Task.Delay(5000);
Monitor.Enter(obj);
try
{
nTasks++;
Console.WriteLine($"nTasks:{nTasks};SubThreadId:{Thread.CurrentThread.ManagedThreadId}");
}
finally
{
Monitor.Exit(obj);
}
}));

}
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("不会堵塞");
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("使用Task.WaitAll(tasks.ToArray());等待tasks子线程结束,才执行主线程:等待子线程结束");
Task.WaitAll(tasks.ToArray());
sw.Stop();
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("开始执行主线程");
Console.WriteLine($"执行时长:{sw.ElapsedMilliseconds}ms");
Console.WriteLine($"nTasks:{nTasks};MainThreadId:{Thread.CurrentThread.ManagedThreadId}");
Console.ForegroundColor = ConsoleColor.White;
}
catch(AggregateException e)
{
String msg = String.Empty;
foreach (var ie in e.InnerExceptions)
{
Console.WriteLine("{0}", ie.GetType().Name);
if (!msg.Contains(ie.Message))
msg += ie.Message + Environment.NewLine;
}
Console.WriteLine("\nException Message(s):");
Console.WriteLine(msg);
}
Console.ReadLine();
}

效果

Monitor测试