本帖最后由 weiwuyuan 于 2011-10-16 13:22:28 编辑

解决方案 »

  1.   

    你没有实现同步,而且Sleep(1), 应该说,比任何API同步方式都慢.
      

  2.   


    这跟Sleep(1)没有关系,加Sleep(1)的原因是我的应用是在游戏程序中,不加Sleep会把CPU耗光。
    我的这种方式主要是为了解决数据冲突问题。我认为,没有哪种方式比这个更快。是0等待。
      

  3.   

    我的应用是这样的:
    我的游戏在每一帧都要渲染一张图片,这张图片在创建之初,就一直出于渲染状态(有个变量记录是否已加载完,加载完才会渲染)。
    而线程则后台对图片的像素进行加载,加载完后,则标记加载完的状态。
    为了两者不冲突,我加入了这种线程同步方式,这种方式是某个朋友提出来的,我发现他相当的strong,不仅不存在冲突问题,而且是0等待。
      

  4.   

    这种用全局变量来进行同步的方法就是写程序简单点,对2个线程的简单应用也许可以, 更多的线程肯定会晕头转向了,因为那个全局变量任何线程都可能写.而且死循环会使CPU 100%,你也发现了,不是你说的0等待,而是一直在死等. 而用WaitForSingleObject这些函数时候, 就会让出CPU给其它线程.
      

  5.   

    看来这种方法的确strong,连InterlockedExchange都不需要用。直接一个变量就可以完美解决冲突问题。
      

  6.   

    你的方法,首先根本没有做自旋等待,几乎是直接退出来了。其次,就算是自旋等待,也不用Sleep(1),而是Sleep(0),更短的等待可以用指令pause,即写__asm pause;还有更致命的一点,你没在临界变量前用volatile修饰,release版会把你的代码优化掉。其实还有一个更重要的问题,只是被你的错误掩盖了,我现在不说,等你改正了现有的错误再说。
      

  7.   


    另外,跟Sleep没有关系,是我一开始没把要解决的问题阐述清楚。
      

  8.   


    你根本保证不了。你知道所谓“CPU写入存储”,或者叫“合并写入”的机制吗?
      

  9.   

    连volatile都没有,release版里会被优化掉。
      

  10.   


    你根本不想去了解。对IA32体系结构而言,有合并写入的设计。当一个写入操作被CPU提交至总线的时候(即要求总线将值写入相应的内存),如果总线忙,则将这个操作计入Write Store里,等待总线空闲的时候,总线将Store中的所有写入操作一并完成。这就是“合并写入”,会导致写入操作延迟。有几种情况将强制将Store中写入操作flush到内存,其中一种就是有lock指令前缀被执行的时候,将强制导致Store刷新。这就是为什么在这种内存同步的时候(栅栏指令也会导致Store刷新,所以仅使用栅栏指令时不必要使用lock)要使用lock类前缀操作(在windows里就是Interlocked系列函数)。
      

  11.   

    而且,楼主,我再教你一个:   像这种代码:   while (g_Open == FALSE)
        {
            // do something
             a = 1;  // 我加的代码
            g_Open = TRUE;
            Sleep(1);
        }假如你的本意是用g_Open变量的真假值来保护变量a的存取一致性,而其实,在两方面,你都难以达到目的:1. 优化器会打乱代码的顺序,比如,上面的代码,编译完之后可能会等价于下面的代码:        a = 1; 
            g_Open = TRUE;    优化器生成的代码可能会等价于:
            g_Open = TRUE;
            a = 1;    所以,你根本无法这样保护变量a。2 IA32的CPU指令优化:即使优化器是按照你想要的顺序生成代码,一旦代码在IA32的CPU里执行,CPU也会调整指令的执行顺序。有的读操作会被提前到写操作之前。比如:
        
        mov a, eax   //  写操作
        mov ebx, b   //  读操作    可能会被CPU优化为等价代码:    mov ebx, b   //  读操作
        mov a, eax   //  写操作
        
        
           
     
      

  12.   

    要验证优化器会打乱原始代码顺序,这个比较简单,看我博客文章:《volatile的单纯语义》。
      

  13.   


    哦,对,这个我没有写好,我原来的程序结构是这样的:线程函数()
    {
        while (true)
        {
            调用函数()
            {
               if (g_Open == FALSE)
               {
                  ....
               }
            }
           Sleep(1)
        }
    }然后主线程也是如此的,我的这个子线程就是帮主线程在后台加载数据。。