上一题下一题
跳转到
 
 
  世界如此多姿,发展如此迅速,窥一斑未必还能知全豹。但正如万花筒一样,每一个管窥都色彩斑斓。  
 
 
  知识通道 | 学习首页 | 教师首页 | PK首页 | 知识创造首页 | 企业首页 | 登录
 
本文对应知识领域
关于dictionary多线程安全的写法,究竟是应该使用“读写锁”,还是仅仅只锁住“写”
作者:未知 申领版权
2010年10月13日 共有 3641 次访问 【添加到收藏夹】 【我要附加题目
受欢迎度:

    关于“读写锁”:在锁住时,读的时候可以多线程并发,但是一旦开始写入,则其余的“写”以及其余的“读”都等待直到“写”结束方能访问此对象。
    仅锁住“写”:“写”的时候锁住线程,此时其它“写”不能访问此对象,但是其它读可以访问此对象。若使用“读写锁”,则“写”的时候,“读”线程也不能访问。
    对于Dictionary 类的同步,通常都有两种方法,其一是仅锁住“写”,但是读不锁。
    实现方法如下:
            public void add(tkey key, tvalue value)        {            lock (syncroot)            {                d.add(key, value);            }        }其二是用“读写锁”,这篇文章写得很详细,通时对性能进行了评测:
    http://www.cnblogs.com/JeffreyZhao/archive/2009/11/12/concurrent-cache-performance-improvement-1-immutable-hash-table.html
    在此文章中提到仅仅锁住“写”是不行的,对此我不敢苟同。
    第一:hash表的读的方法是以下几步:①获得表的基本信息,②根据表的基本信息计算key的hash值,就是将byte的移位,速度非常快,③根据hash值在数组中查找数据。这几步任意一步都不影响表结构本身,也就是说“读”不对“写”造成影响,也就是说在“写”的同时进行“读”是不会破坏链表的。但是“写”会对“读”造成影响,因为“写”本身可能会使内存扩容,可能会遇到碰撞而重新hash等因素,使“读”的第一步获得的表的基本信息是过时的,然后第二步第三步就出问题。但是这种几率非常小,为什么这么说呢,因为hash表中的读,速度非常快,就是几步byte移位以及一个定位操作,经过测试,加“读写锁”后,在单线程中光是“锁”的操作时间就是“读”的操作时间的两倍,在多个线程中切换时“锁”的操作时间可能数倍于“读”的操作时间。实际上测试读1千万次都只需要几百毫秒,而“读”出错的时候仅限于“写”时恰好扩容或者“写”时悄好发生hash同值碰撞的那一瞬间,这么夸张的小几率事件,若对程序要求不是特别特别的高,不是银行系统,则是不需要考虑的。
    官方对于dictionary的线程安全是这样描述的:
    “只要不修改该集合,Dictionary 就可以同时支持多个阅读器。即便如此,从头到尾对一个集合进行枚举本质上并不是一个线程安全的过程。当出现枚举与写访问互相争用这种极少发生的情况时,必须在整个枚举过程中锁定集合。若要允许多个线程访问集合以进行读写操作,则必须实现自己的同步。”
    那么分析可得,官方认为“写”是一定不安全的,光“读”是一定安全的。“读写”同时操作时,“枚举”和“写”同时操作时有“极少发生”的互相争用对象的几率。“枚举”相当于一次性连续读取全部hash表数据,若hash表有一万个数据,则需要枚举一万次,时间上和读取一次,相差万倍,就算这样,官方仍旧认为是小概率事件。
    所以,最后我认为,在网络应用程序中,如web网页应用中,对于dictionary,仅仅“写”锁定,以及“枚举”锁定就可以,“读”是不需要锁定的。万一万一恰好恰好读的时候出错了怎么办?呵呵,那也很好办啊,再刷新一下页面就是了。只要写锁定了,链表就不会出错,对系统本身就不构成影响。比方说若一秒钟写入一次数据,写入数据耗时大约10倍于读取,就算1千万分之一秒写入,其中恰好扩容或者碰撞开始影响表结构的一瞬间算几亿分之一秒,然后读取的时间也是一亿分之一秒。这个相乘就是出错的几率,再呢,很多写入的时候并不扩容,也不碰撞,则出错的几率更低。出现读错的现象几率估计是几十亿 亿分之一吧。而且读错了对程序本身是没有影响的,仅对一个页面反应有影响。
    

    

 

相关新闻

并行思维2
数据结构HashTable
数据结构HashTable2
C# TryGetValue Method

您可能对这些感兴趣  

用VB做定时断线程序
VisualBasic中的界面设计原则和编程技巧
VB6.0与Windows API 间的呼叫技巧
制作可以自动隐藏的弹出式菜单
ListBox中的字符串超长显示的解决方法
VB中的Unicode 和 Ansi 格式
优化程序显示速度
Visual Basic 产生渐层的 Form 背景
用VB实现客户——服务器(TCP/IP)
用VB制作注册软件的方法

题目筛选器
日期:
类型:
状态:
得分: <=
分类:
作者:
职业:
关键字:
搜索

 
 
 
  焦点事件
 
  知识体系
 
  职业列表
 
 
  最热文章
 
 
  最多引用文章
 
 
  最新文章
 
 
 
 
网站介绍 | 广告服务 | 招聘信息 | 保护隐私权 | 免责条款 | 法律顾问 | 意见反馈
版权所有 不得转载
沪ICP备 10203777 号 联系电话:021-54428255
  帮助提示    
《我的太学》是一种全新的应用,您在操作中遇到疑问或者问题,请拨打电话13564659895,15921448526。
《我的太学》