日期:2014-05-17  浏览次数:21058 次

Thread.VolatileWrite的原子性操作问题,求助!
首先Thread.VolatileWrite和Thread.VolatileRead是基于原子操作的,直接上一例子吧,看我理解的对不对

现在有一个公共资源Int64 n;CPU是32位的
假如把一个VolatileWrite这个操作放慢速度,执行这个方法是需要10s

问题1:
线程1正在执行VolatileWrite(ref n,0x0123456789abcdef)
线程2在线程1正执行VolatileWrite的时候,要执行VolatileRead(ref n),假如线程1中的VolatileWrite执行了一半,即过了5秒,那么线程2中的VolatileRead是不是要等5秒后VolatileWrite执行完后才能执行?
反过来,线程1正在VolatileRead的时候,线程2中的VolatileWrite是不是也要待VolationRead后才能执行,否则VolatileWrite则处于阻塞状态,尽管阻塞很短很短的时间

问题2:
如果两个线程都同时,注意是同时执行VolatileRead(ref n),对于两个线程来讲,在这时是不是不存在阻塞,类似于ReaderWriterLock中的读锁
线程 Volatile 原子操作

------解决方案--------------------
首先不可能执行那么慢。变量也是一次性的变化的,不存在中间状态。

就按你假设的情况来说吧:
问题1:是要“阻塞”(其实是空转,并没有真正阻塞,因为是用户模式构造),这个线程协调是通过cpu指令来的,在硬件中发生,所以非常快。又读写速度非常快,几乎可以忽略空转时间。

问题2:如上面提到的,线程的协调是通过cpu指令来的,但具体怎么做,我不清楚。但既然是只读的操作,我认为这里不会存在冲突,所以不会“阻塞”。
------解决方案--------------------
个人猜测“同时执行VolatileRead”也会互相阻塞,原因是VolatileRead应该是CPU指令级别的原子操作,是很基础的操作。我选择相信VolatileRead可以作为其它同步操作,比如ReaderWriterLock等的基石,而不是相反。
------解决方案--------------------
LZ所想的问题的确是存在的,主要是CPU的“乱序优化”造成的,前的高级处理器,为了提高内部逻辑元件的利用率以提高运行速度,通常会采用多指令发射、乱序执行等提高性能

volatile变量和MemoryBarrier宏指令会被汇编代码中保留下来,并且按照优化前的指令顺序和多少被原封不动
而其他变量则会被优化成寄存器操作

在C++中对于双检锁创建单例的bug,就常用MemoryBarrier来解决,包括.Net中封装的InterlockedExchange等也用到了

所以是会阻塞的,一种内核级(汇编)的自旋锁
http://hi.baidu.com/crazii_chn/item/6440edd016888595270ae742