首页 新闻 会员 周边 捐助

对“对象的多线程读操作是安全的,必须使任何写操作同步”的理解

0
悬赏园豆:15 [已解决问题] 解决于 2013-08-21 16:57

比如,DataTable对象,MSDN对它的线程安全性是这么说的:“该类型对于多线程读操作是安全的。  您必须使任何写操作同步。”

我要问的是:对于这种对象,在多线程环境下,是不是只需要对写操作进行lock,而不必对读操作进行lock,就可以保证线程安全 ?

还有Dictionary<TKey, TValue>,MSDN说的是:


只要不修改该集合,Dictionary<TKey, TValue> 就可以同时支持多个阅读器。  即便如此,从头到尾对一个集合进行枚举本质上并不是一个线程安全的过程。  当出现枚举与写访问互相争用这种极少发生的情况时,必须在整个枚举过程中锁定集合。  若允许多个线程对集合执行读写操作,您必须实现自己的同步。

是否也只需要对写操作进行lock,而不必对读操作进行lock,就可以保证线程安全 ?

问题补充:

那我再追问一下,我的一个全局静态DataTable,写操作是lock了的,那么在读取时,对它的Select方法返回DataRow[],或它的Rows集合,进行遍历操作,这两种情况,是否需要把遍历操作进行lock呢?

戒焦戒躁的主页 戒焦戒躁 | 初学一级 | 园豆:15
提问于:2013-08-20 16:29
< >
分享
最佳答案
0

如果只是保证线程安全,只需要对写操作进行加锁就行了,多线程并行写一块内存是会出现内存错误的。

多个线程并行的读一块内存数据本身是不会出错的,但是会出现上下文不一致的设计上的问题。比如一个线程读取了数据在还没来得及显示出来时,原数据被另外一个线程改变了,等你显示出来的时候,显示的结果和原数据已经不一样了。为了保证上下文一致就读加锁。好像买火车票一样,一个人在买一张票,读取剩余票数还剩1张,结果在点击去确定的时候被已经被另外一个人(另一个线程)买走了。其实没有余票了,给了假象,读加锁就是防止这个出现的。

如果只是简单的刷新数据,比如上位机软件不断采集PLC数据保存到表中更新已有数据,那么多个线程就不需要加锁,因为所有线程只是为了把数据读取出来而已,为了保证数据的时时性,所有线程都竭力最快的读取上来。这个时候加锁,就变得跟单线程一样了。

当然前提是保证读取的数据存在,如果在一个线程准备读一个数据之前,数据被另一个线程删除了,这个删除不是清零是完全删除了BUFF,那么就会出错。关键根据你程序的需要来保证线程安全

收获园豆:7
大芝麻 | 初学一级 |园豆:4 | 2013-08-21 09:57

 当出现枚举与写访问互相争用这种极少发生的情况时,必须在整个枚举过程中锁定集合。  若允许多个线程对集合执行读写操作,您必须实现自己的同步。

 

大芝麻 | 园豆:4 (初学一级) | 2013-08-21 17:19
其他回答(2)
0

不是。特别对于枚举操作,在枚举过程中修改集合,可能会重置枚举器,从而造成访问冲突。

写操作包括:添加、删除、修改。

修改不影响读,但是删除会影响,而添加的话就要视集合实现添加的方式而定。

收获园豆:5
Launcher | 园豆:45050 (高人七级) | 2013-08-20 16:44
0

人家说的很清楚了,“若允许多个线程对集合执行读写操作,您必须实现自己的同步”。不光是写,多线程读,也要加锁。

收获园豆:3
上帝之城 | 园豆:2549 (老鸟四级) | 2013-08-20 17:09
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册