我是多线程编程的新手。我尝试使用偶数和奇数打印线程打印数字序列,并行运行。执行时,代码进入死锁状态。任何人都可以帮我解决这个问题。
#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);
}
}
答案 0 :(得分:1)
该计划至少有一些问题:
您永远不会初始化条件变量:
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;
}
现在您可以看到如何避免死锁。线程只有在知道需要等待条件时才开始等待条件。因此,即使第二个线程在第一个线程没有等待它时发出信号,这也没关系。
答案 1 :(得分:1)
我认为要做好工作,你需要三个互斥锁和三个条件变量。奇数线程必须在程序的整个持续时间内保持奇数互斥锁的锁定。奇数互斥锁解锁的唯一时间是奇数线程在其状态下等待。同样,偶数线程需要在持续时间内保持偶数互斥锁。
并且您需要一个主互斥量和一个主要条件变量,这样奇数和偶数线程可以在锁定各自的互斥锁后发出主信号。
奇数和偶数线后
- 正在运行中
- 锁定了他们的互斥锁
- 并等待他们的条件变量(解锁互斥锁)
然后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 );
}
答案 2 :(得分:0)
首先,条件变量未初始化为&#34; PTHREAD_COND_INTIALIAZER&#34;。来到程序,在第一个线程中,我认为pthread_mutex_unlock应该在pthread_cond_signal之前出现
答案 3 :(得分:0)
以下代码 - 删除不需要的系统函数调用 - 正确处理互斥锁创建/锁定/解锁/销毁 - 从0到49绘制偶数/奇数值 - 正确处理错误记录 - 修改关于未定义函数exit()的编译器警告 - 停止线程在内部while循环中被锁定 - 正确地将顶线程函数定义为&#39; void *&#39;而不是&#39; void&#39; - 将参数设置为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