0

我有 ac 程序在 Linux 内核 2.6.18-194 中运行,服务器有 1 个带有 6 核的超线程 cpu 套接字,线程 1 接收数据,然后线程 2 和线程 3 将线程 1 接收到的数据传递给另一个进程,线程 2 和线程 3 都成功后传完数据,thread1会再次接收数据!!

流动的是 thread1 来源:

        DoGetDataFromSocket() ;
        iGlbBOOKReadDone = 0 ;
        iGlbPOSIReadDone = 0 ;
        sem_post(sembook) ;
        sem_post(semposi) ;
        sem_wait(semfinished) ;

以下是thread2和thread3的源码:

    if(bThisThreadIsBook==1)
        sem_wait(sembook) ;
    else
        sem_wait(semposi) ;

    DoPassDatatoAnotherProcess() ;

    if(bThisThreadIsBook==1)
    {
        __sync_add_and_fetch(&iGlbBOOKReadDone,1) ;
    }
    else
    {
        __sync_add_and_fetch(&iGlbPOSIReadDone,1) ;
    }

    Pthread_mutex_lock(&DoneMutex) ;
    if(  (iGlbBOOKReadDone == 1) && (iGlbPOSIReadDone == 1) )
        sem_post(semfinished) ;
    Pthread_mutex_unlock(&DoneMutex) ;

它对我来说很好,我尝试删除 thread2 和 thread3 中的 mutex_lock DoneMutex ,它仍然可以正常工作,我很好奇的是,如果 thread2 正在执行 __sync_add_and_fetch(&iGlbBOOKReadDone,1) ,并且 thread3 正在执行 __sync_add_and_fetch(&iGlbPOSIReadDone,1)完全相同的时间,那么两个线程都会将 if( (iGlbBOOKReadDone == 1) && (iGlbPOSIReadDone == 1) ) 设为 false ,并且永远不会调用 sem_post(semfinished) ,但是我做了很多压力测试,这永远不会发生!!它与 __sync_add_and_fetch 函数有关吗?

4

1 回答 1

2

正如我在评论中提到的,无论您是否使用互斥锁,您都有一个semfinished可以发布信号两次的竞争条件,这意味着thread1可能不允许线程在未来一轮中完成。

很容易看出,两者都thread2可以在通话thread3之前同时“到达”空白行。pthread_mutex_lock()如果发生这种情况,那么两个线程都会调用sem_post(semfinished).

为了避免这种情况并使代码更易于推理,使您可以确定thread2thread3 will callsem_post(semfinished) 中的一个,您可能需要考虑执行以下操作:

  • 线程1:

    DoGetDataFromSocket() ;
    threadDoneCount = 0;
    sem_post(sembook) ;
    sem_post(semposi) ;
    sem_wait(semfinished) ;
    
  • 线程 2 和线程 3:

    if(bThisThreadIsBook==1)
        sem_wait(sembook) ;
    else
        sem_wait(semposi) ;
    
    DoPassDatatoAnotherProcess() ;
    
    int doneCount = __sync_add_and_fetch(&threadDoneCount,1) ;
    
    if (doneCount == 2)
        sem_post(semfinished) ;
    
于 2013-02-18T14:06:59.687 回答