今天同事告诉我, 锁 hashtable 应该锁它的 SyncRoot 属性而不应该锁它的实例, 例如:

Hashtable ht = new Hashtable();
lock(ht.SyncRoot)
{
...
}

看了 .Net Framework 文档, 给的例子也是锁 SyncRoot 属性, 说如果锁实例的话不能保证在并发情况下的同步, 我很疑惑, 为什么不能锁 hashtable 实例本身呢?

做了个实验, 两个线程 A 和 B, 用锁实例和锁 SyncRoot 两种方式测试, 都没有问题, 结果是一样的。

后来, 用 Hashtable.Synchronized 创建自动线程同步的 hashtable, 终于明白了 SyncRoot 的作用。先说说自动线程同步的 Hashtable: 如果 Hashtable 要允许并发读但只能一个线程写, 要这么创建 Hashtable 实例:

Hashtable hashtable = Hashtable.Synchronized(new Hashtable());

这样, 如果有多个线程并发的企图写 hashtable 里面的 item, 则同一时刻只能有一个线程写, 其余阻塞; 对读的线程则不受影响。

测试的代码是这样的:

Hashtable _hashtable = Hashtable.Synchronized(new Hashtable());

public void TestLock()
{
Thread t1 = new Thread(new ThreadStart(SyncFunctionA));
Thread t2 = new Thread(new ThreadStart(SyncFunctionB));

t1.Start();
t2.Start();

Thread.Sleep(8000);

Console.WriteLine("hashtable[" + _key_a + "] = " + _hashtable[_key_a]);
}

private void SyncFunctionA()
{
lock (_hashtable.SyncRoot)
{
Thread.Sleep(5000);
_hashtable[_key_a] = "Value set by SyncFunctionA";
}
}

private void SyncFunctionB()
{
Console.WriteLine("hashtable[" + _key_a + "] = " + _hashtable[_key_a]);
_hashtable[_key_a] = "Value set by SyncFunctionB";

}

为了清楚的看到效果, 线程 A 用了锁, 并睡眠 5 秒, 睡醒后设置一下 hashtable 里的 item. 线程 B 先读一下 hashtable 里的 item, 再写 hashtable 里的 item。因为对 SyncRoot 加了锁, 即使线程 B 没有显式的对 hashtable 加锁, 但在 _hashtable[_key_a] = "Value set by SyncFunctionB" 一句上也会被 hashtable 自动锁住, 直到线程 A 释放掉 SyncRoot 锁为止。如果线程 A 不是锁 SyncRoot 而是锁 hashtable 实例本身, 那么线程 B 不会在 _hashtable[_key_a] = "Value set by SyncFunctionB" 上被自动锁住。

所以, 总结如下:

如果想锁整个 hashtable, 包括读和写, 即不允许并发的读和写, 那应该锁 hashtable 实例;
如果想允许并发的读, 不允许并发的写, 那应该创建 Synchronized 的 hashtable, 并对要加锁的一块代码用 SyncRoot 锁住, 如果不需要对一块代码加锁, 则 hashtable 会自动对单个写的操作加锁。

转载于:https://www.cnblogs.com/hyfei0315/articles/1238627.html

一个 .Net Hashtable 的锁的疑惑和解决相关推荐

  1. 从0设计一个基于Redis的锁服务

    作者:温灏,后端研发,专注于Python和Go,对分布式系统感兴趣,本文系作者投稿,有兴趣投稿的同学,请后台回复[投稿] 由于微服务大行其道,服务之间的协调工作变得越来越重要.今天来简单说一下如何搭建 ...

  2. 深入Lock锁底层原理实现,手写一个可重入锁

    synchronized与lock lock是一个接口,而synchronized是在JVM层面实现的.synchronized释放锁有两种方式: 获取锁的线程执行完同步代码,释放锁 . 线程执行发生 ...

  3. 【设置一个类似手机的锁屏界面但又不知道如何操作——下载加速吧】

    对于很多公共办公场所来说,经常会需求临时离开一会,比如去喝水或者上厕所.如果这个时候,我们希望电脑上的东西部被他们动到或者看到该怎么办呢?这是今日有网友问到的一个类似问题,网友希望在离开的时候,可以设 ...

  4. 一个多线程死锁案例,如何避免及解决死锁问题

    转载自 一个多线程死锁案例,如何避免及解决死锁问题 多线程死锁在java程序员笔试的时候时有遇见,死锁概念在之前的文章有介绍,大家应该也都明白它的概念,不清楚的去翻看历史文章吧. 下面是一个多线程死锁 ...

  5. mysql锁表原因及解决

    mysql锁表原因及解决 问题如图 锁表发生原因 锁表发生在 insert.update.delete中: 锁表的原理是数据库使用独占式锁机制,当执行上面的语句时,对表进行锁住,直到发生commit或 ...

  6. MySQL--死锁的原因及解决方法

    原文网址:MySQL--死锁的原因及解决方法_IT利刃出鞘的博客-CSDN博客 简介 说明 本文介绍MySQL死锁的原因及解决方法. InnoDB中,除单个SQL组成的事务外,锁是逐步获得的,所以可能 ...

  7. 如何解除计算机方向键问题,笔记本键盘上下左右键怎么解锁_笔记本电脑的上下左右键被锁住了如何解决-win7之家...

    我们在电脑中玩游戏的时候,经常会使用到键盘上下左右键来进行操作,不过有不少笔记本用户反映说键盘上下左右键被锁住了,导致无法操作,但是这种情况不多见,如果被锁定的话.一般是数字区域,方向键基本上没有被锁 ...

  8. Python GIL锁问题探究及解决

    1. 什么是GIL? GIL即全局解释器(global interpreter lock).python的每个线程在执行时都需要先获取GIL,保证同一时刻只有一个线程可以执行代码,即同一时刻只有持有G ...

  9. python gil 解除_详解Python中的GIL(全局解释器锁)详解及解决GIL的几种方案

    先看一道GIL面试题: 描述Python GIL的概念, 以及它对python多线程的影响?编写一个多线程抓取网页的程序,并阐明多线程抓取程序是否可比单线程性能有提升,并解释原因. GIL:又叫全局解 ...

最新文章

  1. 已知环境静态障碍物避障_我女儿如何教我无障碍环境
  2. IBM推出127量子比特处理器,超越谷歌和中科大
  3. Spark编程模型几大要素
  4. C#.Net工作笔记003---异步编程async await_在开发中的使用经验_随时更新
  5. caffe安装_【开源框架】caffe图像分类从模型自定义到测试
  6. paip.Adblock屏蔽onlinedown华军软件园的4秒下载广告总结..
  7. ad18 bell封装_Altium 中异形焊盘异形封装的创建图文教程
  8. 虎牙直播Js说书人弹幕
  9. SQL Server表空间碎片化回收
  10. 50 岁的程序员该何去何从?
  11. 免企业资质免签约支付
  12. 图论(九)有向图和网络
  13. 一种高效的q+1准均匀量化(quasi-uniform quantization)方法及MATLAB实现
  14. Nature Cell Biology:揭示 PI3K-Akt 信号通路新机制,有望成为癌症治疗新靶点
  15. 八招教你解决网络故障!
  16. Linux 入门视频教程
  17. 机架服务器和群晖存文件对比,如何选购群晖nas网络存储服务器?
  18. python比较日期时间_python时间如何比较
  19. Qt Creator不同Qt版本切换
  20. layui 表格隐藏id列

热门文章

  1. lambda中的钩子函数
  2. Hibernate执行原理总结
  3. linux 句柄_linux 文件句柄数查看命令
  4. C++设计模式--状态模式(state)
  5. Java中在一个字符串的固定位置插入字符串
  6. 强化学习6——Value-based RL和Policy-based RL 的区别
  7. java写大文件_java实现超大文件的读写功能
  8. Linux / argv、environ 和 env 的联系
  9. 数据结构与算法 / 排序算法(3)
  10. 结构体字节大小计算方法