2016-02-20 38 views
1

我想了解有關線程和鎖定,並編寫了一個程序,以使用兩個線程分別打印偶數和奇數的序列來打印數字。但似乎進入了僵局。有人能告訴我我做錯了什麼嗎?試圖在C中使用線程順序打印數字

/* 
    threads printing even odd number without shared variable 
*/ 
#include <stdio.h> 
#include <pthread.h> 

pthread_mutex_t mux = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t even = PTHREAD_COND_INITIALIZER; 
pthread_cond_t odd = PTHREAD_COND_INITIALIZER; 

void print_even() 
{ 
    int i = 0; 
    do { 
     pthread_mutex_lock(&mux); 
     pthread_cond_wait(&odd, &mux); 
     i+=2; 
     printf("%d ", i); 
     pthread_cond_signal(&even); 
     pthread_mutex_unlock(&mux); 
    } while (i<100); 
} 

void print_odd() 
{ 
    int i = 1; 
    do { 
     pthread_mutex_lock(&mux); 
     pthread_cond_wait(&even, &mux); 
     i+=2; 
     printf("%d ", i); 
     pthread_cond_signal(&odd); 
     pthread_mutex_unlock(&mux); 
    } while (i<100); 
} 

int main() 
{ 
    pthread_t podd, peven; 
    pthread_mutex_init(&mux, NULL); 
    printf("The values are:\n"); 
    pthread_create(&podd, NULL, (void *)&print_odd, NULL); 
    pthread_create(&peven, NULL, (void *)&print_even, NULL); 
    pthread_mutex_lock(&mux); 
    pthread_cond_signal(&even); 
    pthread_mutex_unlock(&mux); 
    pthread_join(podd, NULL); 
    pthread_join(peven, NULL); 
    printf("\ndone\n"); 
    return 0; 
} 
+0

線程的要點在於,除非試圖訪問由它們共享的數據,否則它們可以彼此免費,這取決於誰先到達並確保數據一致。爲什麼翻轉和翻牌? –

+2

當沒有人在等待時,你發出信號。不管怎樣,'print_even'和'print_odd'需要在'main'發送第一個信號之前發信號通知'main'它們已準備就緒(即鎖定它們各自的互斥鎖)。所以你需要三個互斥體,每個互斥體用於'main','print_odd'和'print_even',以及兩個線程用來發信號給main的另一個條件變量。 – user3386109

+0

@ user3386109啊,是的。由於信號在任何人等待之前發送得太早,所以基本上已經丟失。感謝您的回答。 – themoreyouknow

回答

0

在使用條件變量的方式中存在缺陷。對你而言,他們自己似乎是溝通的渠道,需要完成某些事情。相反,使用它們作爲指標來檢查當前狀態是否需要做任何事情。

僞代碼:

mutex m 
condition_var odd 
condition_var even 
integer i 

function handle odd numbers: 
    lock(m) 
    while true: 
     if i is odd: 
     print i 
     increment i 
     signal even 
     wait odd 

function handle even numbers: 
    lock(m) 
    while true: 
     if i is even: 
     print i 
     increment i 
     signal odd 
     wait even 

main: 
    i = 0 
    start thread to handle odd numbers 
    start thread to handle even numbers 

正如所看到的,等待之前,該線程檢查該共享計數器是奇數還是偶數,然後相應地動作。但是,它不需要該事件,特別是在啓動main()中的線程和發信號事件之間沒有競爭條件。

聲明:這是如何使用條件變量,但它絕不是好的MT編程!確保你閱讀並理解給你的問題的評論!

+0

感謝您的解釋! – themoreyouknow

0

作爲user3386109由主程序發送的信號提及@是太快(前print_odd線程準備好了),因此丟失導致被僵持兩個線程。將編輯程序並儘快發佈代碼。

#include <stdio.h> 
#include <pthread.h> 
#include <stdlib.h> 

pthread_mutex_t even_mux = PTHREAD_MUTEX_INITIALIZER; 
pthread_mutex_t odd_mux = PTHREAD_MUTEX_INITIALIZER; 
pthread_mutex_t main_mux = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t even = PTHREAD_COND_INITIALIZER; 
pthread_cond_t odd = PTHREAD_COND_INITIALIZER; 
pthread_cond_t ready = PTHREAD_COND_INITIALIZER; /* to signal main that the 
                threads are created */ 
void print_even() 
{ 
    pthread_mutex_lock (&even_mux); 

    pthread_mutex_lock (&main_mux); 
    pthread_cond_signal (&ready); 
    pthread_mutex_unlock (&main_mux); 

    int i = 0; 
    do { 
     pthread_cond_wait (&even, &even_mux); 
     i += 2; 
     printf ("%d ", i); 
     pthread_mutex_lock (&odd_mux); 
     pthread_cond_signal (&odd); 
     pthread_mutex_unlock (&odd_mux); 
    } while (i < 100); 

    pthread_mutex_unlock (&even_mux); 
} 

void print_odd() 
{ 
    pthread_mutex_lock (&odd_mux); 

    pthread_mutex_lock (&main_mux); 
    pthread_cond_signal (&ready); 
    pthread_mutex_unlock (&main_mux); 

    int i = 1; 
    do { 
     pthread_cond_wait (&odd, &odd_mux); 
     i += 2; 
     printf ("%d ", i); 
     pthread_mutex_lock (&even_mux); 
     pthread_cond_signal (&even); 
     pthread_mutex_unlock (&even_mux); 
    } while (i < 100); 

    pthread_mutex_unlock (&odd_mux); 
} 

int main (void) 
{ 
    pthread_t podd, peven; 
    pthread_mutex_init (&odd_mux, NULL); 
    pthread_mutex_init (&even_mux, NULL); 
    pthread_mutex_init (&main_mux, NULL); 

    printf ("The values are:\n"); 

    pthread_mutex_lock (&main_mux); 
    if (pthread_create (&podd, NULL, (void *) &print_odd, NULL) != 0) { 
     exit (1); 
    } 
    pthread_cond_wait (&ready, &main_mux); 

    if (pthread_create (&peven, NULL, (void *) &print_even, NULL) != 0) { 
     exit (1); 
    } 
    pthread_cond_wait (&ready, &main_mux); 

    pthread_mutex_unlock (&main_mux); 
    pthread_mutex_lock (&even_mux); 
    pthread_cond_signal (&even); 
    pthread_mutex_unlock (&even_mux); 
    pthread_join (podd, NULL); 
    pthread_join (peven, NULL); 
    printf ("\ndone\n"); 

    return 0; 
} 
+0

*注意:*您的值從'2'開始打印。你需要將'i'的增量順序交換到'printf(「%d」,i);我+ = 2;' –

+0

這不能解決*任何*。僅僅因爲你不明白條件變量和信號量之間的差異並不意味着你需要寫出這種(破壞的)可憎的東西。 – EOF