基础知识重要吗?真的很重要。
就在笔者与同事聊天中突然同事提出一个问题,让笔都有点乱了手脚(有点夸张),题目是这样的:
问: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 实现并发情况下,既有读线程,又有写线程的线程安全实例:

 private Hashtable _ht = Hashtable.Synchronized(new Hashtable());
static void Main(string[] args)
{
new Program().TestLock();
Console.WriteLine($"主线程:{Thread.CurrentThread.ManagedThreadId}");
Console.ReadKey();
} public void TestLock()
{
Task.Factory.StartNew(obj => SyncMethodA((string)obj), "laowang");
Task.Factory.StartNew(obj => SyncMethodB((string)obj), "liupangzi");
Thread.Sleep();
Console.WriteLine($"输出值:{ _ht[0]}");
} private void SyncMethodA(string param)
{
Console.WriteLine($"方法A线程:{Thread.CurrentThread.ManagedThreadId}");
lock (_ht.SyncRoot)
{
Thread.Sleep();
_ht[] = "SyncMethodA";
Console.WriteLine($"A方法输出值:{ _ht[0]}");
}
} private void SyncMethodB(string param)
{
Console.WriteLine($"方法B线程:{Thread.CurrentThread.ManagedThreadId}");
Console.WriteLine($"B方法输出值:{ _ht[0]}");
_ht[] = "SyncMethodB";
}
 
     为了看到效果,线程A使用了锁,并睡眠 5 秒,后设置 hashtable 值为 SyncMethodA ,线程B先读取 hashtable 中的值,再写入 SyncMethodB 值到 hashtable 中。在写入值这句上会被 hashtable 自动销锁住 ,直到A释放掉 SyncRoot 为止。
     上面代码中我们实现锁 SyncRoot 方式进行测试,结果:
     
   如果我们更改锁的对象为 hashtable 实例本身,lock(_ht) ,那么线程B不会在 hashtable="SyncMethodB" 这句话自动锁住。所以输出值是:SyncMethodA
注:以上代码请忽略方法传值      
        
    

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

  1. C# Synchronized 和 SyncRoot 实现线程同步的源码分析及泛型集合的线程安全访问

    转载:http://blog.csdn.net/zztfj/article/details/5640889 Synchronized vs SyncRoot 我们知道,在.net的一些集合类型中,譬如 ...

  2. [转帖]C#中字典集合HashTable、Dictionary、ConcurrentDictionary三者区别

    C#中字典集合HashTable.Dictionary.ConcurrentDictionary三者区别 https://blog.csdn.net/yinghuolsx/article/detail ...

  3. Java中的集合和线程安全

    通过Java指南我们知道Java集合框架(Collection Framework)如何为并发服务,我们应该如何在单线程和多线程中使用集合(Collection). 话题有点高端,我们不是很好理解.所 ...

  4. 通过Collections将集合转换为线程安全类集合

    通过Collections将集合转换为线程安全类集合 List集合: List<String> list=new ArrayList<String>();list.add(&q ...

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

    建议22:确保集合的线程安全 集合线程安全是指多个线程上添加或删除元素时,线程键必须保持同步. 下面代码模拟了一个线程在迭代过程中,另一个线程对元素进行了删除. class Program { sta ...

  6. Vector、HashTable线程不安全示例

    下面这样写法是Vector线程不安全的写法: import java.util.Vector; public class Test { private static Vector<Integer ...

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

    Java并发编程之-set集合的线程安全类 Java中set集合怎么保证线程安全,这种方式你知道吗? 在Java中set集合是 本篇是<凯哥(凯哥Java:kagejava)并发编程学习> ...

  8. Day10_53_Collections.synchronizedList() 将Arraylist集合转换为线程安全的集合

    将Arraylist集合转换为线程安全的集合 import java.util.ArrayList; import java.util.Collections; import java.util.Li ...

  9. C#中字典集合HashTable、Dictionary、ConcurrentDictionary三者区别

    C#中HashTable.Dictionary.ConcurrentDictionar三者都表示键/值对的集合,但是到底有什么区别,下面详细介绍 一.HashTable HashTable表示键/值对 ...

随机推荐

  1. 高级Java开发工程师

  2. springmvc 中RequestMapping注解的使用

    1.RequestMapping注解既可以修饰方法,又可以修饰类型,类型指定的url相对于web跟路径,而方法修饰的url相对于类url: 2.RequestMapping的几个属性: value:用 ...

  3. Kendo UI - Class 基类定义

    在 kendo 中,使用原型继承机制,Class 是 Kendo 中的基类,定义了函数 extend 用来派生其它类. function Class() {} Class.extend = funct ...

  4. MFC学习 MFCActiveX控件

    例子包含 1. 重绘activex控件显示区域 在activex的ctrl类中ondraw中实现 2.添加修改activex控件属性(前景色, 背景色, 自定义属性),, 只要在类视图中展开libra ...

  5. 浅谈Java的包装类

    一.什么是Java包装类 所谓Java包装类,就是将Java中的8种基本数据类型分别包装成为类的形式.包装类与基本数据类型的对应关系如下表所示. 基本数据类型 包装类 byte Byte short ...

  6. Dll学习(二)__declspec用法详解

    __declspec用于指定所给定类型的实例的与Microsoft相关的存储方式.其它的有关存储方式的修饰符如static与extern等是C和 C++语言的ANSI规范,而__declspec是一种 ...

  7. 【练习】增加日志组数至4组,且每组日志成员大小为50M,每组2个成员。

    1.查看日志组成员路径及日志组大小.状态 SQL> select group#,member from v$logfile; GROUP# MEMBER ---------- --------- ...

  8. Oracle 删表前验证表名是否存在并且删除

    DECLARE num NUMBER; BEGIN SELECT COUNT(1) INTO num FROM USER_TABLES WHERE TABLE_NAME = UPPER('tableN ...

  9. QTP动态加载对象库

    Public Function AddObjectRepository(path) On Error Resume Next Dim pos, repath If instr(path,". ...

  10. 一目了然c++虚基类!

    #include <IOSTREAM.H> //基类 class CBase ...{ protected: int a; public: CBase(int na) ...{ a=na; ...