问题描述
|
我需要使用互斥锁(仅)在2个线程之间实现屏障同步。屏障同步是2个线程将在预定义的步骤互相等待,然后再继续。
我可以使用seamaphore来做到这一点,但是我如何仅使用互斥锁来做到这一点。提示我需要2个互斥锁而不是1个。
使用Seamaphore:
#include <pthread.h>
#include <semaphore.h>
using namespace std;
sem_t s1;
sem_t s2;
void* fun1(void* i)
{
cout << \"fun1 stage 1\" << endl;
cout << \"fun1 stage 2\" << endl;
cout << \"fun1 stage 3\" << endl;
sem_post (&s1);
sem_wait (&s2);
cout << \"fun1 stage 4\" << endl;
}
void* fun2(void* i)
{
cout << \"fun2 stage 1\" << endl;
cout << \"fun2 stage 2\" << endl;
// sleep(5);
sem_post (&s2);
sem_wait (&s1);
cout << \"fun2 stage 3\" << endl;
}
main()
{
sem_init(&s1,0);
sem_init(&s2,0);
int value;
sem_getvalue(&s2,&value);
cout << \"s2 = \" << value << endl;
pthread_t iThreadId;
cout << pthread_create(&iThreadId,NULL,&fun2,NULL) << endl;
// cout << pthread_create(&iThreadId,NULL) << endl;
pthread_create(&iThreadId,&fun1,NULL);
sleep(10);
}
将以上代码编译为\“ g ++ barrier.cc -lpthread \”
解决方法
没有杂物和锁怎么办?仅使用原子操作:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h>
static sigset_t _fSigSet;
static volatile int _cMax=20,_cWait = 0;
static pthread_t _aThread[1000];
void * thread(void *idIn)
{
int nSig,iThread,cWait,id = (int)idIn;
printf(\"Start %d\\n\",id,_cMax);
// do some fake weork
nanosleep(&(struct timespec){0,500000000},NULL);
// barrier
cWait = __sync_add_and_fetch(&_cWait,1);
printf(\"Middle %d,%d/%d Waiting\\n\",_cMax);
if (cWait < _cMax)
{
// if we are not the last thread,sleep on signal
sigwait(&_fSigSet,&nSig); // sleepytime
}
else
{
// if we are the last thread,don\'t sleep and wake everyone else up
for (iThread = 0; iThread < _cMax; ++iThread)
if (iThread != id)
pthread_kill(_aThread[iThread],SIGUSR1);
}
// watch em wake up
cWait = __sync_add_and_fetch(&_cWait,-1);
printf(\"End %d,%d/%d Active\\n\",_cMax);
return 0;
}
int main(int argc,char** argv)
{
pthread_attr_t attr;
int i,err;
sigemptyset(&_fSigSet);
sigaddset(&_fSigSet,SIGUSR1);
sigaddset(&_fSigSet,SIGSEGV);
printf(\"Start\\n\");
pthread_attr_init(&attr);
if ((err = pthread_attr_setstacksize(&attr,16384)) != 0)
{
printf(\"pthread_attr_setstacksize failed: err: %d %s\\n\",err,strerror(err));
exit(0);
}
for (i = 0; i < _cMax; i++)
{
if ((err = pthread_create(&_aThread[i],&attr,thread,(void*)i)) != 0)
{
printf(\"pthread_create failed on thread %d,error code: %d %s\\n\",i,strerror(err));
exit(0);
}
}
for (i = 0; i < _cMax; ++i)
pthread_join(_aThread[i],NULL);
printf(\"\\nDone.\\n\");
return 0;
}
,我不确定您是否需要两个互斥锁,其中一个互斥锁和一个条件变量以及一个额外的标志可能就足够了。这个想法是通过获取互斥锁进入关键部分,然后检查是否是第一个进入的线程,如果是,则等待条件。如果您是第二个线程,那么您将唤醒等待的线程,并且两个线程都将离开。