C线程打印数字序列:偶数和奇数打印线程并行运行

我是multithreading编程的新手。 我尝试使用偶数和奇数打印线程打印数字序列,并行运行。 执行时,代码进入死锁状态。 任何人都可以帮我解决这个问题。

#include #include pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t even, odd; void printfun1(void *pnt); void printfun2(void *pnt); main() { pthread_t pthread1, pthread2; int ret1, ret2; char *message = "thread 1"; char *message2 = "thread 2"; ret1 = pthread_create(&pthread1, NULL, printfun1, (void *)message); if(ret1) { printf("thread creation failed"); } ret2 = pthread_create(&pthread2, NULL, printfun2,(void*) message2); if(ret2) { printf("thread creation failed"); } pthread_join(pthread1, NULL); pthread_join(pthread2, NULL); exit(0); } void printfun1(void *ptr) { char* message = ptr; int counter = -1; while(counter < 50) { pthread_mutex_lock(&mutex); pthread_cond_wait(&even, &mutex); counter += 2; printf("%d \n", counter); pthread_cond_signal(&odd); pthread_mutex_unlock(&mutex); usleep( 1000000); } } void printfun2(void *ptr) { char* message = ptr; int counter2 = 0; pthread_cond_signal(&even); while(counter2 < 50) { pthread_mutex_lock(&mutex); pthread_cond_wait(&odd, &mutex); counter2 += 2; printf("%d \n", counter2); pthread_cond_signal(&even); pthread_mutex_unlock(&mutex); usleep( 1000000); } } 

该计划至少有一些问题:

  1. 您永远不会初始化条件变量:

     pthread_cond_init(&even, NULL); pthread_cond_init(&odd, NULL); 
  2. 如果在另一个线程没有等待该条件时发出信号,则可以达到死锁。 通常,当您使用pthread_cond_wait() ,您还在while循环中检查其他一些共享变量。 我重写了你的程序来certificate这一点:

     #include  #include  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t even = PTHREAD_COND_INITIALIZER; pthread_cond_t odd = PTHREAD_COND_INITIALIZER; void *printfun1(void *pnt); void *printfun2(void *pnt); int main(void) { pthread_t pthread1, pthread2; int ret1, ret2; ret1 = pthread_create(&pthread1, NULL, printfun1, NULL); if(ret1) { printf("thread creation failed"); } ret2 = pthread_create(&pthread2, NULL, printfun2, NULL); if(ret2) { printf("thread creation failed"); } pthread_join(pthread1, NULL); pthread_join(pthread2, NULL); } int counter = 0; void *printfun1(void *ptr) { while(counter < 50) { pthread_mutex_lock(&mutex); while ((counter & 1) == 1) pthread_cond_wait(&even, &mutex); printf("%d \n", counter); counter++; pthread_cond_signal(&odd); pthread_mutex_unlock(&mutex); usleep( 1000000); } return NULL; } void *printfun2(void *ptr) { while(counter < 50) { pthread_mutex_lock(&mutex); while ((counter & 1) == 0) pthread_cond_wait(&odd, &mutex); printf("%d \n", counter); counter++; pthread_cond_signal(&even); pthread_mutex_unlock(&mutex); usleep( 1000000); } return NULL; } 

    现在您可以看到如何避免死锁。 线程只有在知道需要等待条件时才开始等待条件。 因此,即使第二个线程在第一个线程没有等待时发出信号,也无关紧要。

我认为要做好工作,你需要三个互斥锁和三个条件变量。 奇数线程必须在程序的整个持续时间内保持奇数互斥锁。 奇数互斥锁解锁的唯一时间是奇数线程正在等待它的条件。 同样,偶数线程需要在持续时间内保持偶数互斥锁。

并且您需要一个主互斥量和一个主要条件变量,以便奇数和偶数线程在锁定其各自的互斥锁后可以发出主信号。

经过奇数和偶数线程
– 正在运行
– 锁定了他们的互斥锁
– 正在等待他们的条件变量(解锁互斥锁)
然后main可以通过一次奇数线程来发出信号。

 #include  #include  #include  #include  pthread_mutex_t mainMutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t oddMutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t evenMutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t mainCond = PTHREAD_COND_INITIALIZER; pthread_cond_t oddCond = PTHREAD_COND_INITIALIZER; pthread_cond_t evenCond = PTHREAD_COND_INITIALIZER; void *printOdd( void *arg ) { pthread_mutex_lock( &oddMutex ); // grab the odd mutex pthread_mutex_lock( &mainMutex ); // signal main that the odd thread pthread_cond_signal( &mainCond ); // is locked and ready for action pthread_mutex_unlock( &mainMutex ); for ( int counter = 1; counter < 50; counter += 2 ) { pthread_cond_wait( &oddCond, &oddMutex ); // wait for the odd signal printf( "%d\n", counter ); pthread_mutex_lock( &evenMutex ); // signal the even thread pthread_cond_signal( &evenCond ); pthread_mutex_unlock( &evenMutex ); usleep( 100000 ); } pthread_mutex_unlock( &oddMutex ); return NULL; } void *printEven( void *arg ) { pthread_mutex_lock( &evenMutex ); // grab the even mutex pthread_mutex_lock( &mainMutex ); // signal main that the even thread pthread_cond_signal( &mainCond ); // is locked and ready for action pthread_mutex_unlock( &mainMutex ); for ( int counter = 2; counter < 50; counter += 2 ) { pthread_cond_wait( &evenCond, &evenMutex ); // wait for the even signal printf( "%d\n", counter ); pthread_mutex_lock( &oddMutex ); // signal the odd thread pthread_cond_signal( &oddCond ); pthread_mutex_unlock( &oddMutex ); usleep( 100000 ); } pthread_mutex_unlock( &evenMutex ); return NULL; } int main( void ) { pthread_t id1, id2; pthread_mutex_lock( &mainMutex ); // grab the main mutex if ( pthread_create( &id1, NULL, printOdd, NULL ) != 0 ) // create the odd thread exit( 1 ); pthread_cond_wait( &mainCond, &mainMutex ); // wait for the signal from the odd thread if ( pthread_create( &id2, NULL, printEven, NULL ) != 0 ) // create the even thread exit( 1 ); pthread_cond_wait( &mainCond, &mainMutex ); // wait for the signal from the even thread pthread_mutex_unlock( &mainMutex ); // startup has completed, release the main mutex pthread_mutex_lock( &oddMutex ); // signal the odd thread to get things rolling pthread_cond_signal( &oddCond ); pthread_mutex_unlock( &oddMutex ); pthread_join( id1, NULL ); // wait for the threads to finish pthread_join( id2, NULL ); exit( 0 ); } 

首先,条件变量未初始化为“PTHREAD_COND_INTIALIAZER”。 来到程序,在第一个线程中,我认为pthread_mutex_unlock应该在pthread_cond_signal之前出现

以下代码 – 删除不需要的系统函数调用 – 正确处理互斥锁创建/锁定/解锁/销毁 – 从0到49编写偶数/奇数值 – 正确处理错误记录 – 修正编译器关于undefined的警告function exit() – 停止线程在内部while循环中被锁定 – 正确地将顶层线程函数定义为’void *’而不是’void’ – 正确地将参数设置为pthread_create() – 通过pthread_exit正确地退出线程() – 以及其他一些小修正

 #include  #include  // exit(), EXIT_FAILURE #include  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void *printfun1(void *); void *printfun2(void *); main() { pthread_t pthread1, pthread2; int ret1, ret2; ret1 = pthread_create(&pthread1, NULL, &printfun1, (void *)message); if(ret1) { perror("thread 1 creation failed"); exit( EXIT_FAILURE ); } ret2 = pthread_create(&pthread2, NULL, &printfun2,(void*) message2); if(ret2) { perror("thread 2 creation failed"); exit( EXIT_FAILURE ); } pthread_join(pthread1, NULL); pthread_join(pthread2, NULL); pthread_mutex_destroy(&mutex); return 0; } // end function: main int counter = 0; // Note: // 1) 0 is even so should be printed // 2) 50 is beyond the range, so should not be printed // 3) use do{...}while so program will exit when done, // rather than getting locked in wait loop void *printfun1(void *ptr) { do { while( (counter & 1) == 0 ) { usleep(100); } pthread_mutex_lock(&mutex); printf("%d \n", counter); counter++; pthread_mutex_unlock(&mutex); } while( counter < 50 ); pthread_exit( 0 ); } // end function: printfun1 void *printfun2(void *ptr) { do { while( (counter & 1) == 1 ) { usleep(100); } pthread_mutex_lock(&mutex); printf("%d \n", counter); counter++; pthread_mutex_unlock(&mutex); } while( counter < 50 ); pthread_exit( 0 ); } // end function: printfun2