我们知道,在.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. HDOJ(HDU).1015 Safecracker (DFS)

    HDOJ(HDU).1015 Safecracker [从零开始DFS(2)] 从零开始DFS HDOJ.1342 Lotto [从零开始DFS(0)] - DFS思想与框架/双重DFS HDOJ.1 ...

  2. nodejs创建多层目录

    1. fs.mkdir不能一次创建多层目录,必须先创建上层目录,再创建下层目录 //同步 fs.mkdirSync("./tmp/"); fs.mkdirSync("./ ...

  3. React setState和修改props触发的钩子

    1. setState的改变会触发4个生命周期钩子 shouldComponentUpdatecomponentWillUpdaterendercomponentDidUpdate 2. props的 ...

  4. AtCoder Regular Contest 081 E - Don't Be a Subsequence(字符串DP)

    引用自:onion_cyc 字符串DP一直不是强项...以后没思路的题就想DP和网络流23333333 f[i]表示从i开始的后缀非子序列的最短长度  pos[i][j]表示从i开始的j字符最早出现位 ...

  5. Numpy模块(数值计算)

    Numpy是高性能科学计算和数据分析的基础包.它是pandas等其他各种工具的基础. NumPy的主要功能: ndarray,一个多维数组结构,高效且节省空间 无需循环对整组数据进行快速运算的数学函数 ...

  6. 中国MOOC_面向对象程序设计——Java语言_第2周 对象交互_秒计时的数字时钟

    第2周编程题 查看帮助 返回   第2周编程题,在课程所给的时钟程序的基础上修改 依照学术诚信条款,我保证此作业是本人独立完成的. 温馨提示: 1.本次作业属于Online Judge题目,提交后由系 ...

  7. Codeforces Round #342 (Div. 2) A

    A. Guest From the Past time limit per test 1 second memory limit per test 256 megabytes input standa ...

  8. BST POJ - 2309 思维题

    Consider an infinite full binary search tree (see the figure below), the numbers in the nodes are 1, ...

  9. mybatis逆向工程生成mapper报错

    Result Maps collection already contains value for xxxMapper.BaseResultMap错误解决办法一.问题描述今天在做项目时,遇到一个错误: ...

  10. Linux 守护进程创建原理及简易方法

    1:什么是Linux下的守护进程 Linux daemon是运行于后台常驻内存的一种特殊进程,周期性的执行或者等待trigger执行某个任务,与用户交互断开,独立于控制终端.一个守护进程的父进程是in ...