同步块的机制:
- 在.NET被加载时初始化同步块数组
- 每一个被分配在堆上的对象都会包含两个额外的字段,其中一个存储类型指针,而另外一个就是同步块索引,初始时被赋值为-1.
- 当一个线程试图使用该对象进入同步时,会检查该对象的同步索引。如果索引为负数,则会在同步块数组中寻找或者新建一个同步块,并且把同步块的索引值写入该对象的同步索引中。如果该对象的同步索引不为负值,则找到该对象的同步块并且检查是否有其他线程在使用该同步块,如果有则进入等待状态,如果没有则声明使用该同步块。
- 当一个对象退出同步时,该对象的同步索引被赋值为-1,并且对应的同步块数组内的同步块被视为不再使用。
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
62
63
64
|
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Threading;
namespace
MultiThreadTest
{
class
Program
{
static
void
Main(
string
[] args)
{
Console.WriteLine(
"测试静态方法同步?"
);
for
(
int
i = 0; i < 5; i++)
{
Thread t =
new
Thread(Lock.Add1);
t.Start();
}
Thread.Sleep(10 * 1000);
Console.WriteLine(
"测试成成员方法同步"
);
Lock l =
new
Lock();
for
(
int
i = 0; i < 5; i++)
{
Thread t =
new
Thread(l.Add2);
t.Start();
}
Console.Read();
}
}
public
class
Lock
{
// 用来同步静态方法
private
static
object
o1 =
new
object
();
private
static
int
i1 = 0;
// 用来同步成员方法
private
object
o2 =
new
object
();
private
int
i2 = 0;
public
static
void
Add1(
object
state)
{
lock
(o1)
{
Console.WriteLine(
"before add:i1 = {0}"
, i1);
Thread.Sleep(1000);
i1++;
Console.WriteLine(
"after add :i1 = {0}"
, i1);
}
}
public
void
Add2(
object
state)
{
lock
(o2)
{
Console.WriteLine(
"before add:i1 = {0}"
, i2);
Thread.Sleep(1000);
i2++;
Console.WriteLine(
"after add :i1 = {0}"
, i2);
}
}
}
}
|
注意:对静态方法的同步,一般采用静态私有的引用成员,而对成员方法的同步,一般采用私有的引用成员。值类型的对象非配在堆栈上,没有同步索引字段,所以不能用来进行同步。
本文转自敏捷的水博客园博客,原文链接http://www.cnblogs.com/cnblogsfans/archive/2009/11/06/1597453.html如需转载请自行联系原作者
王德水