[英]C Threads to print sequence of numbers : with even and odd number printing threads running parallely
我是多线程编程的新手。 我尝试使用偶数和奇数打印线程打印数字序列,并行运行。 执行时,代码进入死锁状态。 任何人都可以帮我解决这个问题。
#include<stdio.h>
#include<pthread.h>
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);
}
}
该计划至少有一些问题:
您永远不会初始化条件变量:
pthread_cond_init(&even, NULL); pthread_cond_init(&odd, NULL);
如果在另一个线程没有等待该条件时发出信号,则可以达到死锁。 通常,当您使用pthread_cond_wait()
,您还在while循环中检查其他一些共享变量。 我重写了你的程序来演示这个:
#include <stdio.h> #include <pthread.h> 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 <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
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 <stdio.h>
#include <stdlib.h> // exit(), EXIT_FAILURE
#include <pthread.h>
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.