我们知道,在.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属性原理分析的更多相关文章

  1. iOS多线程编程之NSThread的使用

      目录(?)[-] 简介 iOS有三种多线程编程的技术分别是 三种方式的有缺点介绍 NSThread的使用 NSThread 有两种直接创建方式 参数的意义 PS不显式创建线程的方法 下载图片的例子 ...

  2. iOS多线程编程之NSThread的使用(转)

    本文由http://blog.csdn.net/totogo2010/原创 1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation  ...

  3. [转]iOS多线程编程之NSThread的使用

    1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue ...

  4. iOS多线程编程之NSThread的使用(转载)

    1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1.NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue的 ...

  5. [转] iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用

    介绍: Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其他的对称多处理系统的系统.这建立在任务并行执行的线程池模式的基础上的.它首 ...

  6. [转] iOS多线程编程之NSOperation和NSOperationQueue的使用

    <iOS多线程编程之NSThread的使用> 介绍三种多线程编程和NSThread的使用,这篇介绍NSOperation的使用. 使用 NSOperation的方式有两种, 一种是用定义好 ...

  7. iOS 多线程编程之Grand Central Dispatch(GCD)

    介绍: Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其它的对称多处理系统的系统.这建立在任务并行运行的线程池模式的基础上的. 它 ...

  8. iOS多线程编程之NSOperation和NSOperationQueue的使用

    前一篇 <iOS多线程编程之NSThread的使用> 介绍三种多线程编程和NSThread的使用,这篇介绍NSOperation的使用. 使用 NSOperation的方式有两种, 一种是 ...

  9. Android编程之LayoutInflater的inflate方法实例

    假设你不关心其内部实现,仅仅看怎样使用的话,直接看这篇就可以. 接上篇,接下来,就用最最简单的样例来说明一下: 用两个布局文件main 和 test: 当中,main.xml文件为: <?xml ...

随机推荐

  1. bzoj 3280: 小R的烦恼 (网络流)

    和开发计划一样(数组开太小wa了好多次,然后为什么这么慢? type arr=record toward,next,cap,cost:longint; end; const maxm=; maxn=; ...

  2. BZOJ5157 & 洛谷3970:[TJOI2014]上升子序列——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5157 https://www.luogu.org/problemnew/show/P3970 给定 ...

  3. printf函数用法小记

    By francis_hao    Aug 26,2017   C语言中printf函数是一个比较常用的函数,但是常用并不代表完全了解,本文翻译了printf的man手册,介绍了其全部功能(不包括ma ...

  4. IntelliJ IDEA 详细图解最常用的配置 ,适合新人,解决eclipse转idea的烦恼

    刚刚使用IntelliJ IDEA 编辑器的时候,会有很多设置,会方便以后的开发,磨刀不误砍柴工. 比如:设置文件字体大小,代码自动完成提示,版本管理,本地代码历史,自动导入包,修改注释,修改tab的 ...

  5. dubbox小demo

    概述: 我们建立两个web项目,一个是service负责提供服务,另一个是web项目负责调用服务. 两个项目都是 maven Project 项目 生产者项目: 项目中主要就是: pom文件,引入相关 ...

  6. Spring源码解析-autowiring自动装配的实现

    IoC容器提供了自动依赖装配的方式,为应用IoC容器提供很大的方便.在自动配置中,不需要显式的去指定Bean属性,只需要配置autowiring属性,IoC容器会根据这个属性配置,使用反射的方式查找属 ...

  7. HDU 4549 矩阵快速幂+快速幂+欧拉函数

    M斐波那契数列 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Sub ...

  8. HDU3068:最长回文(Manacher模板)

    最长回文 Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  9. ACM1258邻接表

    教训:使用邻接表的时候一定要把邻接表的结构组定义的足够大,不能仅仅等于节点的个数,因为线段的数量往往远超过节点的数量. 这个题目是拓扑排序练习,提高下理解. #include<iostream& ...

  10. Eclipse中安装插件的三种方式

    转载自:http://www.cnblogs.com/lcgustc/archive/2013/01/03/2843496.html Eclipse也用了很久,但是都没有怎么去研究过怎么安装插件,今天 ...