volatile不对代码进行优化和缓存,直接访问内存。并保证在某个线程内,在它之前的代码一定先于它执行,在它之后的代码一定在它后面执行。俺有个问题,如果两个线程在两个cpu上同时写一个volatile共享变量,会不会有访问冲突?为什么?谢谢!

解决方案 »

  1.   

    volatile其实就是一个轻量级的锁啊,编译器不做优化,CPU不做缓存。楼主担心何种冲突?
      

  2.   

    可能会有,因为volatile只是通过编译器不生成寄存器指令来防止单CPU下多线程并发执行指令时数据的不一致性,在某些多CPU情况下仅仅用volatile指示忽略寄存器是不够的,因为每个CPU内部会对内存做部分镜像以加快运行效率,这时就需要在读写的时候先申请总线锁同步内存来防止并发冲突,.net里可以用Thread.MemoryBarrier进行相关操作。
      

  3.   

    谢谢两位,这么快!class Program
        {
            static volatile int n = 0;        static void foo1()
            {
                for (int i = 0; i < 100000000; ++i)
                {
                    n = n + 1;
                }
                Console.WriteLine("foo1 complete, n = {0}", n);
            }        static void foo2()
            {
                for (int i = 0; i < 100000000; ++i)
                {
                    n = n + 1;
                }
                Console.WriteLine("foo2 complete, n = {0}", n);
            }        static void Main(string[] args)
            {
                new Thread(foo1).Start();
                new Thread(foo2).Start();
            }
        }就是说这段代码 如果在多cpu上 可能会有并发冲突?
    code来自: http://blog.csdn.net/huangjf_1983/archive/2008/10/12/3065146.aspx
    网上的资料中几乎没有提到过这一点。
      

  4.   

    顺便说一下,上面的程序在我的机器上(2cpu),跑不出预期的结果:200000000
    总是 10XXXXXXX.
    说明加了volatile,也不是原子操作。如果用interlocked.XXX就没有问题了。所以volatile在多cpu的环境下面用处并不大,这样说对吗?
      

  5.   

    volatile不是用来保证原子操作的,volatile只是用来确保生成的指令跳过寄存器直接访问内存,编译器就算能对volatile编译出il的原子操作指令,真正执行native指令时都不能确保是原子的,必须用framework(如lock/Monitor,Interlocked)来确保原子操作。
      

  6.   

    volatile只是在线程内存和“主”内存间同步某个变量的值,楼主的测试案例是一个绝大部分为写操作的多线程案例,已经超出了volatile的适用场景