C#多线程编程之:集合类中Synchronized方法与SyncRoot属性原理分析
我们知道,在.net的一些集合类型中,譬如Hashtable和ArrayList,都有Synchronized静态方法和SyncRoot属性,他们之间有联系吗?我怎么才能用好他们呢?
以Hashtable为例,看看他们的基本用法:
1 Hashtable ht = Hashtable.Synchronized(new Hashtable());
2 lock (ht.SyncRoot)
3 {
4 ......
5 }
Synchronized表示返回一个线程安全的Hashtable,什么样的 hashtable才是一个线程安全的呢?下边我们就从.NET的源码开始理解。
1 public static Hashtable Synchronized(Hashtable table)
2 {
3 if (table == null)
4 {
5 throw new ArgumentNullException("table");
6 }
7 return new SyncHashtable(table);
8 }
从源码不难看出,Synchronized方法返回的其实是一个SynchHashtable类型的实例。在前边我们说过,Synchronized表示返回一个线程安全的Hashtable,从这个解释不难看出,SynchHashtable应该是继承自Hashtable。下边我们验证一下。看看 SynchHashtable类型的源码:
1 [Serializable]
2 private class SyncHashtable : Hashtable
3 {
4 // Fields
5 protected Hashtable _table;
6
7 // Methods
8 internal SyncHashtable(Hashtable table)
9 : base(false)
10 {
11 this._table = table;
12 }
13
14 internal SyncHashtable(SerializationInfo info, StreamingContext context)
15 : base(info, context)
16 {
17 this._table = (Hashtable)info.GetValue("ParentTable", typeof(Hashtable));
18 if (this._table == null)
19 {
20 throw new SerializationException(Environment.GetResourceString("Serialization_InsufficientState"));
21 }
22 }
23
24 public override void Add(object key, object value)
25 {
26 lock (this._table.SyncRoot)
27 {
28 this._table.Add(key, value);
29 }
30 }
31
32 public override void Clear()
33 {
34 lock (this._table.SyncRoot)
35 {
36 this._table.Clear();
37 }
38 }
39
40 public override object Clone()
41 {
42 lock (this._table.SyncRoot)
43 {
44 return Hashtable.Synchronized((Hashtable)this._table.Clone());
45 }
46 }
47
48 public override bool Contains(object key)
49 {
50 return this._table.Contains(key);
51 }
52
53 public override bool ContainsKey(object key)
54 {
55 return this._table.ContainsKey(key);
56 }
57
58 public override bool ContainsValue(object key)
59 {
60 lock (this._table.SyncRoot)
61 {
62 return this._table.ContainsValue(key);
63 }
64 }
65
66 public override void CopyTo(Array array, int arrayIndex)
67 {
68 lock (this._table.SyncRoot)
69 {
70 this._table.CopyTo(array, arrayIndex);
71 }
72 }
73
74 public override IDictionaryEnumerator GetEnumerator()
75 {
76 return this._table.GetEnumerator();
77 }
78
79 public override void GetObjectData(SerializationInfo info, StreamingContext context)
80 {
81 if (info == null)
82 {
83 throw new ArgumentNullException("info");
84 }
85 info.AddValue("ParentTable", this._table, typeof(Hashtable));
86 }
87
88 public override void OnDeserialization(object sender)
89 {
90 }
91
92 public override void Remove(object key)
93 {
94 lock (this._table.SyncRoot)
95 {
96 this._table.Remove(key);
97 }
98 }
99
100 internal override KeyValuePairs[] ToKeyValuePairsArray()
101 {
102 return this._table.ToKeyValuePairsArray();
103 }
104
105 // Properties
106 public override int Count
107 {
108 get
109 {
110 return this._table.Count;
111 }
112 }
113
114 public override bool IsFixedSize
115 {
116 get
117 {
118 return this._table.IsFixedSize;
119 }
120 }
121
122 public override bool IsReadOnly
123 {
124 get
125 {
126 return this._table.IsReadOnly;
127 }
128 }
129
130 public override bool IsSynchronized
131 {
132 get
133 {
134 return true;
135 }
136 }
137
138 public override object this[object key]
139 {
140 get
141 {
142 return this._table[key];
143 }
144 set
145 {
146 lock (this._table.SyncRoot)
147 {
148 this._table[key] = value;
149 }
150 }
151 }
152
153 public override ICollection Keys
154 {
155 get
156 {
157 lock (this._table.SyncRoot)
158 {
159 return this._table.Keys;
160 }
161 }
162 }
163
164 public override object SyncRoot
165 {
166 get
167 {
168 return this._table.SyncRoot;
169 }
170 }
171
172 public override ICollection Values
173 {
174 get
175 {
176 lock (this._table.SyncRoot)
177 {
178 return this._table.Values;
179 }
180 }
181 }
182 }
呵呵,果然不出我们所料,SyncHashtable果然继承自Hashtable,SyncHashtable之所有能实现线程的安全操作,就是因为在他们的一些方法中,就加了lock,我们知道,哪一个线程执行了lock操作,在他还没有释放lock之前,其他线程都要处于堵塞状态。 SyncHashtable就是通过这种方法,来实现所谓的线程安全。
现在我们理解了Synchronized的含义和用法,那接下来我们看看他和SyncRoot之间的关系。
SyncRoot表示获取可用于同步 Hashtable 访问的对象,老实说,这个解释不好理解,要想真正理解他的用法,我们还得从源码开始:
1 public virtual object SyncRoot
2 {
3 get
4 {
5 if (this._syncRoot == null)
6 {
7 Interlocked.CompareExchange(ref this._syncRoot, new object(), null);
8 }
9 return this._syncRoot;
10 }
11 }
如果您清楚Interlocked的用法,这段代码没什么难理解的了(不清楚的朋友找GOOGLE吧),Interlocked为多个线程共享的变量提供原子操作。原子操作就是单线程操作。在一个Hashtable实例中,不论我们在代码的任何位置调用SyncRoot,返回的都是同一个object类型的对象。我们在开始写的lock(ht.SyncRoot)和下边的操作作用是一样的:
1 static object obj = new object();
2 lock(obj)
3 {
4 ......
5 }
他们之间不同的是,我们声明的static object类型对象是类型级别的,而SyncRoot是对象级别的。
通过上面的分析,我们都应该能理解Synchronized 和 SyncRoot用法,他们之间的关系就是:
Hashtable 通过Synchronized方法,生成一个SynchHashtable类型的对象,在这个对象的一个方法中,通过lock (this._table.SyncRoot)这样的代码来实现线程安全的操作,其中this._table.SyncRoot返回的就是一个 object类型的对象,在一个SynchHashtable对象实例中,不管我们调用多少次,他是唯一的。
另外,针对泛型集合的线程安全访问,由于泛型集合中没有直接公布SyncRoot属性,所以猛一看好似无从下手。
但是查看集合泛型集合的源代码后就可发现他们实际上都提供了SyncRoot属性。
以下以Queue<T>集合为例。
1 bool ICollection.IsSynchronized
2 {
3 get
4 {
5 return false;
6 }
7 }
8
9 object ICollection.SyncRoot
10 {
11 get
12 {
13 if (this._syncRoot == null)
14 {
15 Interlocked.CompareExchange(ref this._syncRoot, new object(), null);
16 }
17 return this._syncRoot;
18 }
19 }
从以上源代码可以看出,这两个方法都被实现为了显式接口,所以必须将其显式转型为ICollection后才能使用。
1 lock (((ICollection)_queue).SyncRoot)
2 {
3 int item = _queue.Dequeue();
4 }
本文来自CSDN博客,原文链接:http://blog.csdn.net/zztfj/archive/2010/06/01/5640889.aspx
C#多线程编程之:集合类中Synchronized方法与SyncRoot属性原理分析的更多相关文章
- iOS多线程编程之NSThread的使用
目录(?)[-] 简介 iOS有三种多线程编程的技术分别是 三种方式的有缺点介绍 NSThread的使用 NSThread 有两种直接创建方式 参数的意义 PS不显式创建线程的方法 下载图片的例子 ...
- iOS多线程编程之NSThread的使用(转)
本文由http://blog.csdn.net/totogo2010/原创 1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation ...
- [转]iOS多线程编程之NSThread的使用
1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue ...
- iOS多线程编程之NSThread的使用(转载)
1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1.NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue的 ...
- [转] iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用
介绍: Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其他的对称多处理系统的系统.这建立在任务并行执行的线程池模式的基础上的.它首 ...
- [转] iOS多线程编程之NSOperation和NSOperationQueue的使用
<iOS多线程编程之NSThread的使用> 介绍三种多线程编程和NSThread的使用,这篇介绍NSOperation的使用. 使用 NSOperation的方式有两种, 一种是用定义好 ...
- iOS 多线程编程之Grand Central Dispatch(GCD)
介绍: Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其它的对称多处理系统的系统.这建立在任务并行运行的线程池模式的基础上的. 它 ...
- iOS多线程编程之NSOperation和NSOperationQueue的使用
前一篇 <iOS多线程编程之NSThread的使用> 介绍三种多线程编程和NSThread的使用,这篇介绍NSOperation的使用. 使用 NSOperation的方式有两种, 一种是 ...
- Android编程之LayoutInflater的inflate方法实例
假设你不关心其内部实现,仅仅看怎样使用的话,直接看这篇就可以. 接上篇,接下来,就用最最简单的样例来说明一下: 用两个布局文件main 和 test: 当中,main.xml文件为: <?xml ...
随机推荐
- 四连测Day1
题目:链接: https://pan.baidu.com/s/163ycV64ioy7uML7AvRDTGw 密码: p86i T1: 倍增求LCA,minn数组记录最小值 #include<i ...
- BAT-Python面试题
Python语言特性 1 Python的函数参数传递 看两个如下例子,分析运行结果: 代码一: a = 1 def fun(a): a = 2 fun(a) print(a) # 1 代码二: a = ...
- python代码格式规范
目前的规范基于pep-0008 基本格式 缩进 使用4个空格进行缩进 行宽 每行代码尽量不超过80个字符 理由: 这在查看side-by-side的diff时很有帮助 方便在控制台下查看代码 太长可能 ...
- Python学习笔记(Django篇)——3、创建第一个数据库模型
Django里面集成了SQLite的数据库,对于初期研究来说,可以用这个学习. 第一步,创建数据库就涉及到建表等一系列的工作,在此之前,要先在cmd执行一个命令: python manage.py ...
- Shell脚本循环读取文件中的每一行
1.使用for循环 for line in `cat filename` do echo $line done 2.使用for循环 for line in $(cat filename) do ech ...
- Beagleboneblack的MLO文件干了些啥
Beagleboneblack在启动linux之前还有三个启动阶段: ROM code --> MLO --> u-boot --> kernel 先看看ROM code干了 ...
- 2015/9/19 Python基础(15):变量作用域及生成器
变量作用域标识符的作用域是定义为其声明的可应用范围,或者即是我们所说的变量可见性.也就是,我们可以在程序的那个部分去访问一个制定的标识符.全局变量与局部变量定义在函数内的变量有局部作用域,在一个模块中 ...
- 2015/9/1 Python基础(6):列表
列表和字符串类型很相似,是同样的序列式数据类型.但是字符串只能由字符组成,列表可以保留任意数目的Python对象的灵活的容器.Python的列表比C的数组要灵活,数组里面只能是一种类型,列表可以有多种 ...
- JNLP Slave connection error解决办法
Replace in jnlp-file <argument>-workDir</argument> <argument /> with <argume ...
- Activity与Service的回收
Android开发中,一个Application,运行在一个进程中.这个Application的各种组件(四种组件),通常是运行在同一个进程中的.但是,并不是绝对的.由于某种需求,比如,你可以设置Ap ...