c-Pthread中的并发性



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

洪水泛滥1来源:

        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) ;

它对我来说很好,我试图在线程2和线程3中删除互斥锁DoneMutex,它仍然很好,但我很好奇的是,如果线程2正在执行__sync_add_and_fetch(&iGlbBOOKReadDone,1),而线程3正在执行__sync_add_aand_fetch则两个线程都将执行if((iGlbBOOKReadDone==1)&(iGlbPOSIReadDone==1))为false并且sem_post(semfinished)将永远不会被调用,但我做了很多压力测试,这从来没有发生过!!是否与__sync_add_and_fetch函数有关?

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

很容易看出,thread2thread3都可以同时"到达"pthread_mutex_lock()调用之前的空白行。如果发生这种情况,那么两个线程都将调用sem_post(semfinished)

为了避免这种情况,并使代码更容易推理,使其能够确定thread2thread3 will call中的某一个sem_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) ;
    

最新更新