2014-02-25 127 views
0

程序中的兩個線程交替地打印偶數和奇數直到100. 我試過這個,它工作。 是否有訪問內部主共享數據的值,並當該值達到100在C中使用2個線程使用互斥打印奇數和偶數

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

pthread_t tid[2]; 
unsigned int shared_data = 0; 
pthread_mutex_t mutex; 
unsigned int rc; 
//prototypes for callback functions 

void* PrintEvenNos(void*); 
void* PrintOddNos(void*); 

void main(void) 
{ 
    pthread_create(&tid[0],0,&PrintEvenNos,0) 
    pthread_create(&tid[1],0,&PrintOddNos,0); 
    sleep(3); 

    pthread_join(tid[0],NULL); 
    pthread_join(tid[1],NULL); 
} 

void* PrintEvenNos(void *ptr) 
{ 
    pthread_mutex_lock(&mutex); 
    do 
    { 
     if(shared_data%2 == 0) 
     { 
     printf("Even:%d\n",shared_data); 
     shared_data++; 
     } else { 
      rc=pthread_mutex_unlock(&mutex);//if number is odd, do not print, release mutex 
     } 
    } while(shared_data <= 100); 
} 

void* PrintOddNos(void* ptr1) 
{ 
    rc = pthread_mutex_lock(&mutex); 
    do 
    { 
     if(shared_data%2 != 0) 
     { 
      printf("odd:%d\n",shared_data); 
      shared_data++; 
     } else { 
      rc = pthread_mutex_unlock(&mutex);//if number is even, do not print, release mutex 
     } 
    } while(shared_data <= 100); 
} 
+0

嘛,不是嗎?你試過了嗎? –

+0

該程序將打印零個或兩個數字,具體取決於哪個線程先執行然後停止,因爲線程不執行一種內部循環。如果'PrintEvenNos'先運行,它將打印0,將shared_data更新爲1並終止;然後運行'PrintOddNos',打印1,將shared_data更新爲2並終止。如果'PrintOddNos'首先運行,它將打印nothings(shared_data爲0,即偶數),將shared_data更新爲1並終止;然後運行'PrintEvenNos',打印nothings(shared_data爲1,即奇數),將shared_data更新爲2並終止。 – isedev

+0

我堅持試試它!我會盡快嘗試。我只是想了解互斥鎖是如何工作的。 – Nanobrains

回答

4

很少有錯誤,在我之前發佈的代碼中,我糾正了這些錯誤,並且該程序打印了從0到100的偶數和奇數值,我試過了。

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

pthread_t tid[2]; 
unsigned int shared_data = 0; 
pthread_mutex_t mutex; 
unsigned int rc; 
//prototypes for callback functions 

void* PrintEvenNos(void*); 
void* PrintOddNos(void*); 

void main(void) 
{ 
    pthread_create(&tid[0],0,&PrintEvenNos,0); 
    pthread_create(&tid[1],0,&PrintOddNos,0); 
    sleep(3); 

    pthread_join(tid[0],NULL); 
    pthread_join(tid[1],NULL); 
} 

void* PrintEvenNos(void *ptr) 
{ 
    rc = pthread_mutex_lock(&mutex); 
    do 
    { 
     if(shared_data%2 == 0) 
     { 
      printf("Even:%d\n",shared_data); 
      shared_data++; 
     } 
     else 
     { 
      rc=pthread_mutex_unlock(&mutex);//if number is odd, do not print, release mutex 
     } 
    } while (shared_data <= 100); 
} 

void* PrintOddNos(void* ptr1) 
{ 
    rc = pthread_mutex_lock(&mutex); 
    do 
    { 
     if(shared_data%2 != 0) 
     { 
      printf("odd:%d\n",shared_data); 
      shared_data++; 
     } 
     else 
     { 
      rc = pthread_mutex_unlock(&mutex);//if number is even, do not print, release mutex 
     } 
    } while (shared_data <= 100); 
} 
+0

我覺得在必要的時候使用信號變量,從調度程序的角度來看,調度程序嘗試給並行運行線程50-50%的權重,但是不能保證,如果由於調度程序線程第二次啓動有點遲,怎麼辦?可能會錯過一些計數,儘管它是一個假設情景,對此並不確定。 –

0

這是一個引人注目的壞用例線程終止2個線程的方法。有兩個線程簡單地交替工作負載不會給你帶來什麼。總的想法是允許線程在等待某些資源變爲可用時執行其他工作。

如果您的兩個線程在等待有用的工作變得可用時正在做有用的工作或完全沒有任何工作,那麼最好在單個執行線程中完成。

話雖如此,你可以可以工作量分成線程,但你做的方式是有問題的。首先,你的每個線程只是簡單地處理一個數字然後退出,所以你不會得到打印出來的幾百個數字。

其次,即使他們沒有循環,就像每一行:

if(shared_data++ %2 == 0) 

增量共享數據,即使它不應該。這將導致產出中「有趣」的結果。想一想每個線程在切換到另一個線程之前經歷了其循環的許多迭代的情況。

因爲它增加不管當前值的,你可能會看到類似這樣的:

0 2 4 6 7 9 11 13 14 16 18 20 21 23 ... 

線程,將工作的僞代碼要求每個線程做什麼影響數據直到輪到他們。首先,主線程,從你沒有太大的不同:

def main() 
    set item to 0 
    start thread evenThread 
    start thread oddThread 
    wait for evenThread to finish 
    wait for oddThread to finish 
    exit 

然後兩個工作線程,在結構上非常相似:

def evenThread(): 
    grab mutex 
    repeat forever: 
     while item is odd: 
      release mutex 
      yield if possible 
      grab mutex 

     # item now guaranteed to be even 
     print item 
     increment item 
     if item is 101: 
      exit repeat loop 
    release mutex 

def oddThread(): 
    grab mutex 
    repeat forever: 
     while item is even: 
      release mutex 
      yield if possible 
      grab mutex 

     # item now guaranteed to be odd 
     print item 
     increment item 
     if item is 100: 
      exit repeat loop 
    release mutex 

但是,即使你想在一個線程的方式完成這件事,互斥體並不一定是一個很好的方法。有可能每個線程在它完成它的工作後繼續運行,導致浪費的工作(上面的僞代碼的產量是爲了減輕這一點,但我很確定yield不是強制性的pthreads - 但它可能是一個不可移植的擴展)。

有很多好的(即確定性的)方法來實現線程之間的通信,這些線程必須知道控制必須被轉移。例如,諸如條件變量之類的東西。

3
Use condition variable to synchronize both threads and a mutex to protect count 

#include "stdio.h" 
#include "stdlib.h" 
#include "pthread.h" 

pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER; 
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER; 
void *functionCount1(); 
void *functionCount2(); 
int count = 0; 
#define COUNT_DONE 200 

void main() 
{ 
pthread_t thread1, thread2; 
pthread_create(&thread1, NULL, &functionCount1, NULL); 
pthread_create(&thread2, NULL, &functionCount2, NULL); 
pthread_join(thread1, NULL); 
pthread_join(thread2, NULL); 
exit(0); 
} 

// Print odd numbers 
void *functionCount1() 
{ 
    for(;;) { 
    // Lock mutex and then wait for signal to relase mutex 
    pthread_mutex_lock(&count_mutex); 
    if (count % 2 != 0) { 
    pthread_cond_wait(&condition_var, &count_mutex); 
    } 
    count++; 
    printf("Counter value functionCount1: %d\n",count); 
    pthread_cond_signal(&condition_var); 
    if (count >= COUNT_DONE) { 
    pthread_mutex_unlock(&count_mutex); 
    return(NULL); 
    } 
    pthread_mutex_unlock(&count_mutex); 
} 
} 

// print even numbers 
void *functionCount2() 
{ 
    for(;;) { 
    // Lock mutex and then wait for signal to relase mutex 
    pthread_mutex_lock(&count_mutex); 
    if (count % 2 == 0) { 
    pthread_cond_wait(&condition_var, &count_mutex); 
    } 
    count++; 
    printf("Counter value functionCount2: %d\n",count); 
    pthread_cond_signal(&condition_var); 
    if(count >= COUNT_DONE) { 
    pthread_mutex_unlock(&count_mutex); 
    return(NULL); 
    } 
    pthread_mutex_unlock(&count_mutex); 
} 
} 
相關問題