我有一个c程序在Linux内核2.6.18-194中运行,服务器有一个cpu插槽,有6个内核,带有超线程,线程1接收数据,然后线程2和线程3将接收到的数据线程1传递给另一个进程,在线程2和线程3都成功完成数据传递后,线程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) ;

它对我很好,我尝试在thread2和thread3中删除mutex锁DoneMutex,它仍然可以正常工作,我好奇的是,如果thread2正在执行“同步添加”和“提取”(&iGlbBOOKReadDone,1),thread3正在执行“同步添加”和“提取”(&iGlbPOSIReadDone,1)
同时,如果((iGlbBOOKReadDone==1)&((iGlbPOSIReadDone==1))为false,则两个线程都将接受,并且永远不会调用sem_post(semfinished),
但是我做了很多压力测试,从来没有发生过!!是否与同步添加和提取功能有关?

最佳答案

正如我在评论中提到的,无论您是否使用互斥,您都有一个竞争条件,即semfinished符号可以被发布两次,这意味着thread1可能不允许线程在未来一轮中完成。
很容易看出,thread2thread3可以在'cc>调用之前同时“到达”空白行。如果发生这种情况,那么两个线程都将调用pthread_mutex_lock()
为了避免这种情况,并使代码更易于推理,使您可以确定sem_post(semfinished)thread2sem廑u 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) ;

关于c - Pthread中的并发,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14928832/

10-11 04:06