[英]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.