C# 集合 — Hashtable 线程安全

基础知识重要吗?真的很重要。

就在笔者与同事聊天中突然同事提出一个问题,让笔都有点乱了手脚(有点夸张),题目是这样的:

问:Hashtable 是线程安全的吗?

答:…… (沉默中,Yes Or No?Why?)

带着问题我们一步一步的解答:

1、线程安全

概念: 通俗的讲就是多线程访问时,采用了加锁机制,当一个线程操作临界区时,对临界区进行保护,其他线程等前面线程操作完才能排队操作临界区。这样保障数据一致减少数据污染。

2、求证

各种资料显示 Hashtable 的 Synchronized 静态方法提供线程安全。那根据资料信息我们找到源代码,找到 Synchronized 是如何提供线程安全的。

都知道 Hashtable 来自 System.Collections 那我们就从他着手找到 Hashtable 中的静态方法 Synchronized:

从源码中可以看出,Synchronized 返回一个 SyncHashtable 实例。我们接着找 SyncHashtable

SyncHashtable 继承自 Hashtable,之所以实现线程安全操作,因为 SyncHashtable 中就已经增加 lock 、

3、结论

到这里至少能证明 Hashtable 在实现静 Synchroinzed 方法时是线程安全的没错吧!

下面写个实例来说明如何使用 Synchronized 实现并发情况下,既有读线程,又有写线程的线程安全实例:

 1 private Hashtable _ht = Hashtable.Synchronized(new Hashtable());
 2         static void Main(string[] args)
 3         {
 4             new Program().TestLock();
 5             Console.WriteLine($"主线程:{Thread.CurrentThread.ManagedThreadId}");
 6             Console.ReadKey();
 7         }
 8
 9         public void TestLock()
10         {
11             Task.Factory.StartNew(obj => SyncMethodA((string)obj), "laowang");
12             Task.Factory.StartNew(obj => SyncMethodB((string)obj), "liupangzi");
13             Thread.Sleep(6000);
14             Console.WriteLine($"输出值:{ _ht[0]}");
15         }
16
17
18         private void SyncMethodA(string param)
19         {
20             Console.WriteLine($"方法A线程:{Thread.CurrentThread.ManagedThreadId}");
21             lock (_ht.SyncRoot)
22             {
23                 Thread.Sleep(5000);
24                 _ht[0] = "SyncMethodA";
25                 Console.WriteLine($"A方法输出值:{ _ht[0]}");
26             }
27         }
28
29         private void SyncMethodB(string param)
30         {
31             Console.WriteLine($"方法B线程:{Thread.CurrentThread.ManagedThreadId}");
32             Console.WriteLine($"B方法输出值:{ _ht[0]}");
33             _ht[0] = "SyncMethodB";
34         }

为了看到效果,线程A使用了锁,并睡眠 5 秒,后设置 hashtable 值为 SyncMethodA ,线程B先读取 hashtable 中的值,再写入 SyncMethodB 值到 hashtable 中。在写入值这句上会被 hashtable 自动销锁住 ,直到A释放掉 SyncRoot 为止。

上面代码中我们实现锁 SyncRoot 方式进行测试,结果:

  如果我们更改锁的对象为 hashtable 实例本身,lock(_ht) ,那么线程B不会在 hashtable="SyncMethodB" 这句话自动锁住。所以输出值是:SyncMethodA

注:以上代码请忽略方法传值

时间: 2024-10-20 13:33:59

C# 集合 — Hashtable 线程安全的相关文章

Java集合的线程安全用法

线程安全的集合包含2个问题 1.多线程并发修改一 个 集合 怎么办? 2.如果迭代的过程中 集合 被修改了怎么办? a.一个线程在迭代,另一个线程在修改 b.在同一个线程内用同一个迭代器对象进行迭代.修改.迭代.修改. . . 共有有3种解决方案 1.用老的Vector/Hashtable类,上面2个问题都不用担心. Vector/Hashtable所提供的所有方法都是 synchronized的.如果 迭代的过程中数据结构被修改了,迭代器可以反映最新的修改,也不会抛异常.但这种方法效率低下,不

集合中线程安全的类

集合中线程安全的类有:vector,stack,hashtable,enumeration,除此之外均是非线程安全的类与接口 Collection 是对象集合, Collection 有两个子接口 List 和 Set, List 可以通过下标 (1,2..) 来取得值,值可以重复,而 Set 只能通过游标来取值,并且值是不能重复的 ArrayList , Vector , LinkedList 是 List 的实现类 ArrayList 是线程不安全的, Vector 是线程安全的,这两个类底

Java中的集合和线程安全

通过Java指南我们知道Java集合框架(Collection Framework)如何为并发服务,我们应该如何在单线程和多线程中使用集合(Collection). 话题有点高端,我们不是很好理解.所以,我会尽可能的描述的简单点.通过这篇指南,你将会对Java集合由更深入的了解,而且我敢保证,这会对你的日常编码非常有用. 1. 为什么大多数的集合类不是线程安全的? 你注意到了吗?为什么多数基本集合实现类都不是线程安全的?比如:ArrayList,?LinkedList,?HashMap,?Has

编写高质量代码改善C#程序的157个建议——建议22:确保集合的线程安全

建议22:确保集合的线程安全 集合线程安全是指多个线程上添加或删除元素时,线程键必须保持同步. 下面代码模拟了一个线程在迭代过程中,另一个线程对元素进行了删除. class Program { static List<Person> list = new List<Person>() { new Person() { Name = "Rose", Age = 19 }, new Person() { Name = "Steve", Age =

集合,线程总结好文章

集合.线程.lua <DT><H3 ADD_DATE="1509440817" LAST_MODIFIED="1529639454">线程总结</H3> <DL><p> <DT><A HREF="http://www.cnblogs.com/lwbqqyumidi/p/3804883.html" ADD_DATE="1509440820" ICON=

Vector、HashTable线程不安全示例

下面这样写法是Vector线程不安全的写法: import java.util.Vector; public class Test { private static Vector<Integer> vector = new Vector<Integer>(); public static void main(String[] args) { while (true) { for (int i = 0; i < 10; i++) { System.out.println(&qu

Java并发编程之set集合的线程安全类你知道吗

Java并发编程之-set集合的线程安全类 Java中set集合怎么保证线程安全,这种方式你知道吗? 在Java中set集合是 本篇是<凯哥(凯哥Java:kagejava)并发编程学习>系列之<并发集合系列>教程的第二篇: 本文主要内容:Set集合子类底层分别是什么?基于底层为什么set的子类可以存放一个数据?怎么解决set线程安全问题? 一:Set集合子类 Set的三个子类分别是:HaseSet.TreeSet.LinkedHashSet.这三个都是线程不安全的.那么这三个子类

java 集合的线程安全

1.Vector.ArrayList.LinkedList Vector和ArrayList在使用上非常相似,都可用来表示一组数量可变的对象应用的集合,并且可以随机地访问其中的元素. Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好. ArrayList和LinkedList区别:对于处理一列数据项,Java提供了两个类ArrayList和

java——阶段性整理(三)集合、线程、网络编程

一.Vector和ArrayList.ArrayList和LinkedList的区别和联系 1)Vector和ArrayList的区别和联系 实现原理相同,功能相同,都是长度可变的数组结构,很多情况下可以互用 Vector是早期JDK接口,ArrayList是替代Vector的新接口 Vector线程安全,ArrayList重速度轻安全,线程非安全 长度需增长时,Vector默认增长一倍,ArrayList增长50% 2)ArrayList和LinkedList的区别和联系 ArrayList和