一全局变量va,
在线程tha中有如下操作:
    va++;
在线程thb中有如下操作:
    if(va>SomeValue){
       ...
    }对变量va是否要加互斥锁?有哪些方法

解决方案 »

  1.   

    CMutex m_Mutex;
    m_Mutex.Lock();
    if(va>SomeValue){}m_Mutex.UnLock();
      

  2.   

    我认为这样简单的操作没有必要加互斥。原因是,从汇编角度来考虑,++一个数的值只需要一条机器码,而读取一个int型变量的值其最终代码也只是1条代码,所以呢没必要
      

  3.   

    感觉有必要,因为 变量 可能放在寄存器和内存中,可能会导致dirty read,哈,初学,请多指教;
      

  4.   

    问题在于块
    if(va>SomeValue){...}
    是不是作为一个原子操作。
      

  5.   

    如果va是整型,我认为完全没有必要
    如果是双精度浮点数,还是互斥的好
    因为双精度时,if(va>SomeValue)语句是几句组成的,执行到一半的时候可能被改变了va的值,这样就会导致比较语句判断失误。
      

  6.   


    首先,Semigod说的有道理。不过想指正一下,“简单的操作没有必要加互斥”的说法可能不太准确。“任何一个线程对全局变量都实现的是原子操作的话,可以不加互斥操作。”这样说也许更严密一点。“++一个数的值只需要一条机器码,而读取一个int型变量的值其最终代码也只是1条代码,所以呢没必要。”
     
    的确,汇编语言中有和高级语言相似的递增,递减指令。(例如:80x80系列的INC,DEC指令) 
    但我们的编译器真的会向我们想象中的那样,使“++”等于“INC”吗? 
    让实践来检验吧。下边是VC++6.0下,一段C++程序的反汇编信息:...       ...
    119:      int Var1;
    120:      Var1 = 0;
    00401973 C7 45 E4 00 00 00 00 mov         dword ptr [ebp-1Ch],0
    121:
    122:      Var1++;
    0040197A 8B 55 E4             mov         edx,dword ptr [ebp-1Ch]
    0040197D 83 C2 01             add         edx,1
    00401980 89 55 E4             mov         dword ptr [ebp-1Ch],edx
    123:      ...
    ...        ...(注:这里的例子是局部变量的情况,全局变量类似)至于双精度型,或if语句,大家也可以自己检验一下。正像我们看到的,编译器并没有实现我们的想法。
    所以,在Bill没有使他的编译器“更聪明”之前,
    我们最好还是加上互斥操作比较安全。Shinka
    2007.07.17
      

  7.   

    使用Mutex或者临界区都比较占资源,可以参考使用InterlockedIncrement
      

  8.   

    怎么在一个线程里面对队列对象(queue)push()数据,另外一个线程pop()..下面代码为什么不行呢?       在主函数main.cpp中定义全局变量,然后把全局变量q作为参数传递给两个线程类的构造函数..
    queue<char*> q;
     
    CRITICAL_SECTION pLock;    //线程全局变量main()
    {   
       InitializeCriticalSection(&pLock);
       new Thread1( q);
       new Thread2(q);
    }在thread1.cpp中..
    在这个线程中把push数据进入队列,extern  CRITICAL_SECTION pLock;    //线程全局变量在main.cpp中定义void __fastcall captureThread::Execute()
    { while(true)
    {
                    ....
                    /*这里把接收到的数据放入一个公共的数据包缓冲池,这个缓冲池是一个LILO的队列 */                EnterCriticalSection(&lock);
                    q.push(RecvBuf);
                             
                   LeaveCriticalSection(&lock);
    }}在thread2.cpp中,把queue中的数据每处理一个以后就pop出来..extern  CRITICAL_SECTION pLock; //线程全局变量在main.cpp中定义void __fastcall ProcessPacket::Execute()
    {       while(true)
            {
               if( processQueue.empty())
               {
                    //printf("empty");
                    continue;
               }           EnterCriticalSection(&lock);
               buf=q.front();
               processQueue.pop();
               LeaveCriticalSection(lock);
            /*--------------------------------*/
               DecodeIpPack(buf);//处理来自队列的数据
            }
    }还是有问题:如果在thread1中push数据,而在在thread2中根本没有数据可pop()....
      

  9.   

    首先,你需要确定你使用的queue支持多线程,应该是在link的选项中。
    或者如下:
    第一个线程:
    EnterCriticalSection(&lock);
    q.push(RecvBuf);
    SetEvent(hPushEvent);
    LeaveCriticalSection(&lock);
    第二个线程:
    while(TRUE){
    if(WAIT_OBJECT_0!=WaitForSingleObject(hPushEvent,INFINITE))
        break;
    EnterCriticalSection(&lock);
               buf=q.front();
               processQueue.pop();
               LeaveCriticalSection(lock);试试看,没有多想,还应该有更好的方式,但更好的方式取决于你对问题的理解和对技术的平衡
      

  10.   

    整形变量当然用 InterlockedIncrement MSDN都这么说.va++ 需要编译器进行优化,不一定保证单指令就执行完毕.如果考虑多CPU,HT之类的,那就更加当然用InterlockedIncrement 了