在多CPU机器上运行的多线程程序中,我需要使用易失性读/写来访问共享状态(下面的示例代码中的_data)以确保正确性.
换句话说,可以在cpu上缓存堆对象吗?
使用下面的示例并假设多线程将访问GetValue和Add方法,我需要ThreadA能够添加数据(使用Add方法)和ThreadB能够立即查看/获取添加的数据(使用GetValue方法) ).那么我需要向_data添加易失性读/写以确保这一点吗?基本上我不想添加要在ThreadA的cpu上缓存的数据.
/我不是锁定(强制独占线程访问),因为代码需要超快,我不从_data中删除任何数据,所以我不需要锁定_data.
谢谢.
****更新****************************
显然你们认为使用这个例子无锁是不好的主意.但是我可以在这里面对哪些副作用或例外?
如果1个线程正在迭代read值而另一个线程正在迭代update的值,那么Dictionary类型会抛出异常吗?或者我只会遇到"脏读"(在我的情况下会没问题)?
****结束更新****************************
public sealed class Data { private volatile readonly Dictionary_data = new Dictionary (); public double GetVaule(string key) { double value; if (!_data.TryGetValue(key, out value)) { throw new ArgumentException(string.Format("Key {0} does not exist.", key)); } return value; } public void Add(string key, double value) { _data.Add(key, value); } public void Clear() { _data.Clear(); } }
谢谢你的回复.关于锁,这些方法几乎经常被多个线程调用,所以我的问题是有争议的锁而不是实际的锁操作.
所以我的问题是关于cpu缓存,可以将堆对象(_data实例字段)缓存在cpu上吗?我是否需要使用易失性读/写访问_data字段?
/另外,我坚持使用.Net 2.0.
谢谢你的帮助.
在MSDN文档的Dictionary
说,它是多个安全的读者,但他们不给了"一个作家,多个读者"保证一些其他类的功能.简而言之,我不会这样做.
你说你正在避免锁定,因为你需要代码"超快" - 你试过锁定以查看开销是多少?无可争议的锁是非常便宜的,当锁被争议时,你会从增加的安全性中受益.在决定担心无锁解决方案的并发问题之前,我肯定会对此进行广泛的分析.ReaderWriterLockSlim
如果你真的有多个读者可能会有用,但听起来你有一个读者和一个单独的作者,至少在目前 - 在这种情况下简单的锁定会更容易.
我想您可能误解了volatile
关键字的使用(无论是我或是,有人请随时纠正我).该volatile
关键字保证从多个线程变量本身的价值get和set操作会一直处理同一个副本.例如,如果我有一个bool
指示状态,那么在一个线程中设置它将使新值立即可用于另一个.
但是,您永远不会更改变量的值(在本例中为引用).你所做的只是操纵参考指向的内存区域.将其声明为volatile readonly
(如果我的理解是合理的,通过永不允许设置来破坏volatile的目的)将不会对被操纵的实际数据(后端存储Dictionary<>
)产生任何影响.
所有这一切,在这种情况下你真的需要使用锁.你的危险超出了"脏读"的前景(意味着你所读的内容在某些时候是有效的)进入真正未知的领域.正如乔恩所说,在你试图走上无锁编码的道路之前,你确实需要证明锁定会产生不可接受的性能.否则,这是过早优化的缩影.