我有一个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
可能不允许线程在未来一轮中完成。
很容易看出,thread2
和thread3
可以在'cc>调用之前同时“到达”空白行。如果发生这种情况,那么两个线程都将调用pthread_mutex_lock()
。
为了避免这种情况,并使代码更易于推理,使您可以确定sem_post(semfinished)
和thread2
sem廑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/