我写了以下简短的申请来解决障碍问题。 此应用程序应保证运行相同线程方法的三个相同线程将在公共代码段“全部”满足。 我跑了它似乎没问题。 我的问题是:
1)这是对的吗?
2)是否有一种首选且有效的方法为N个线程实现它?
这是代码:
static sem_t t_1_sem;
static sem_t t_2_sem;
static sem_t t_3_sem;
struct my_thread_info {
int num;
};
void *thread(void *vargp)
{
struct my_thread_info *info = (struct my_thread_info*)vargp;
static int counter=0;
counter++;
if (info->num == 1) {
printf("info->num=%d\n", info->num);
if (counter<3)
sem_wait(&t_1_sem); // down
else {
sem_post(&t_2_sem); // up
sem_post(&t_3_sem); // up
}
} else
if (info->num == 2) {
printf("info->num=%d\n", info->num);
if (counter<3)
sem_wait(&t_2_sem);
else {
printf("info->num=%d\n", info->num);
sem_post(&t_1_sem);
sem_post(&t_3_sem); //up
}
}
else
if (info->num == 3) {
printf("info->num=%d\n", info->num);
if (counter<3)
sem_wait(&t_3_sem);
else {
sem_post(&t_1_sem);
sem_post(&t_2_sem); //up
}
}
printf("meeting occured!\n");
}
int main()
{
pthread_t tid0, tid1, tid2;
struct my_thread_info info1, info2, info3;
info1.num = 1;
sem_init(&t_1_sem, 0, 0);
sem_init(&t_2_sem, 0, 0);
sem_init(&t_3_sem, 0, 0);
pthread_create(&tid0, NULL, thread, &info1);
info2.num = 2;
pthread_create(&tid1, NULL, thread, &info2);
info3.num = 3;
pthread_create(&tid2, NULL, thread, &info3);
pthread_join(tid0, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
pause();
return 0;
}
问候 凯文
答案 0 :(得分:0)
首先,您的counter
变量无人看守 - 您在执行counter++
时可能存在竞争条件。使用互斥锁;
至于做N个线程 - 使用线程/信号量数组是IMO可接受的,我有使用该设计的代码,它运行良好。
答案 1 :(得分:0)
1.不正确。执行counter++;
之类的增量会导致竞争条件,并且不会正确递增计数器。你想用一个关键部分包围它。
2
static pthread_mutex_t cs_mutex = PTHREAD_MUTEX_INITIALIZER;
static sem_t t_sem;
void *thread(void *vargp)
{
static int counter=0;
pthread_mutex_lock( &cs_mutex );
counter++;
pthread_mutex_unlock( &cs_mutex );
if( counter == NO_THREADS )
sem_post( &t_sem );
sem_wait( &t_sem );
sem_post( &t_sem );
}
int main( int argc, char *argv[] ){
pthread_t tids[NO_THREADS];
sem_init( &t_sem, 0, 0 );
for( i=0; i<NO_THREADS; i++ ){
pthread_create(&tids[i], NULL, thread, NULL);
}
for( i=0; i<NO_THREADS; i++ ){
pthread_join(&tids[i], NULL);
}
pause();
return 0;
}