首先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.   

    首先不可能执行那么慢。变量也是一次性的变化的,不存在中间状态。就按你假设的情况来说吧:
    问题1:是要“阻塞”(其实是空转,并没有真正阻塞,因为是用户模式构造),这个线程协调是通过cpu指令来的,在硬件中发生,所以非常快。又读写速度非常快,几乎可以忽略空转时间。问题2:如上面提到的,线程的协调是通过cpu指令来的,但具体怎么做,我不清楚。但既然是只读的操作,我认为这里不会存在冲突,所以不会“阻塞”。
      

  2.   

    个人猜测“同时执行VolatileRead”也会互相阻塞,原因是VolatileRead应该是CPU指令级别的原子操作,是很基础的操作。我选择相信VolatileRead可以作为其它同步操作,比如ReaderWriterLock等的基石,而不是相反。
      

  3.   

    你好,非常感谢,“这个线程协调是通过cpu指令来协调的”这句话怎么理解呢?还有,什么是“空转”呀,不好意思,好菜,不太懂
      

  4.   


    这里的“这个线程协调是通过cpu指令来协调的” 是不是这样理解的,比如多CPU中,一个CPU对一个变量进行写操作,另一个CPU对一个变量进行读操作时,发现这个变量正在写入,所以调用了一些特殊的CPU,对其中一个指令进行类似“自旋”的操作,或者类型一个什么都不做的指令?
    那如果在单CPU时,涉及到两个线程的时间片的切换,例如一个线程正在写入,由于CPU是32位,变量是64位,当这个线程写了一半,这时写的线程时间片到了,要切换到Read线程时,这时CPU是怎么协调的呢?
      

  5.   


    这里的“这个线程协调是通过cpu指令来协调的” 是不是这样理解的,比如多CPU中,一个CPU对一个变量进行写操作,另一个CPU对一个变量进行读操作时,发现这个变量正在写入,所以调用了一些特殊的CPU,对其中一个指令进行类似“自旋”的操作,或者类型一个什么都不做的指令?
    那如果在单CPU时,涉及到两个线程的时间片的切换,例如一个线程正在写入,由于CPU是32位,变量是64位,当这个线程写了一半,这时写的线程时间片到了,要切换到Read线程时,这时CPU是怎么协调的呢?不同结构的CPU有不同的指令集,这些指令集就是一些数字符号,汇编语言的指令就对应CPU指令。
    我觉得应该是在寄存器中设置标识来协调的,具体什么指令,如何协调我不清楚。“空转”是指线呢并不会真正的阻塞。而是仍会占用CPU资源。
      

  6.   

    LZ所想的问题的确是存在的,主要是CPU的“乱序优化”造成的,前的高级处理器,为了提高内部逻辑元件的利用率以提高运行速度,通常会采用多指令发射、乱序执行等提高性能volatile变量和MemoryBarrier宏指令会被汇编代码中保留下来,并且按照优化前的指令顺序和多少被原封不动
    而其他变量则会被优化成寄存器操作在C++中对于双检锁创建单例的bug,就常用MemoryBarrier来解决,包括.Net中封装的InterlockedExchange等也用到了所以是会阻塞的,一种内核级(汇编)的自旋锁
    http://hi.baidu.com/crazii_chn/item/6440edd016888595270ae742