簡體   English   中英

C線程打印數字序列:偶數和奇數打印線程並行運行

[英]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);
    }
}

該計划至少有一些問題:

  1. 您永遠不會初始化條件變量:

     pthread_cond_init(&even, NULL); pthread_cond_init(&odd, NULL); 
  2. 如果在另一個線程沒有等待該條件時發出信號,則可以達到死鎖。 通常,當您使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM