2017-09-02 77 views
0

我想打印主線程中的奇數和新線程中的偶數。我試圖編寫一個程序,但它只打印奇數而不是偶數。我試圖尋找線索,以找到什麼是錯的,但沒有找到任何。無法打印偶數和奇數異步

這是我的代碼。

#include<stdio.h> 
#include<stdlib.h> 
#include<pthread.h> 
#define MAX 1000 

int count = 0; 

void print_odd_numbers(); 
void *print_even_numbers(); 

int main() { 
    pthread_t t; 
    int iret; 
    iret = pthread_create(&t, NULL, print_even_numbers, NULL); 
    print_odd_numbers();   
    pthread_join(t, NULL); 
    return 0; 
} 

void print_odd_numbers() { 
    while(count <= MAX) { 
     if(count % 2 == 1) { 
      printf("%d\n", count); 
     } 
     count++; 
    } 
} 

void *print_even_numbers() { 
    while(count <= MAX) { 
     if(count % 2 == 0) { 
      printf("%d\n", count); 
     } 
     count++; 
    } 
    pthread_exit(NULL); 
} 
+2

每個線程都需要有自己的 '計數' 變量。不要使用全局變量! –

+0

@MartinJames我見過很多程序,他們保持統計全球。實際上這兩個線程應該並行運行,所以它們的計數應該相同。據我所知。如果我錯了,請幫忙。 –

+1

@Priyanka Naik不,這是不正確的。原因與CPU緩存一致性有關。除非您正在使用旨在以緩存一致方式自動遞增共享值的特定操作,否則您可以讓兩個CPU(或多個核)每個迭代它們自己的緩存中的變量副本,然後將它們的副本寫回到有一點。另外,編譯器不必重新讀取內存中的值,但這是另一回事。 –

回答

1

兩個print_odd_numbersprint_even_numbers增量count即使他們不顯示任何信息的事實是這裏很多麻煩的來源。

所有增量countprint_odd_numbers進行,並count將被設置爲MAXprint_even_numbers之前被啓動。

製作count本地的功能可以幫助,或者是多在count遞增如何是另一種方式更加謹慎 - 如果你保留它的全球性質,那麼你應該考慮使用原子增量

+0

好吧..會盡量讓他們本地一個函數 –

+0

根據我的說法,這些線程應該共享一個公共地址空間,因此這兩個線程應該有一個公共的變量計數,並且這些進程應該並行運行 –

+0

或者使用一個互斥鎖保護對資源的訪問('count' )在線程之間共享。 –

0

如果你不讓編譯器知道你的count被多個線程使用,那麼它可以完全重新排列你的代碼。例如,編譯器可能改變print_odd_numbers到更多的東西一樣

void print_odd_numbers() { 
    if (count <= MAX) { 
     if(count % 2 == 1) { 
      printf("%d\n", count); 
     } 
     count++; 
    } 
    while(count <= MAX) { 
     printf("%d\n", count); 
     count += 2; 
    } 
} 

此外,每個CPU或核心將與它自己的count副本中工作,因爲我們有這麼多所有這些真棒CPU的緩存是加快速度。除非你以某種方式讓你的編譯器知道這個內存位置被其他線程使用,那麼每個線程(如果運行在它自己的內核上)將只使用自己的副本,然後在某個時候將該值寫回主內存。

您需要使用原子增量指令或使用互斥鎖,臨界區,信號量等保護您的全局。當您使用信號量,互斥鎖等時,編譯器自動生成LOCK指令(在x86或類似的對於其他拱形),這迫使CPU在CPU和內核之間以一致的方式管理緩存中的內存。

pthreads: If I increment a global from two different threads, can there be sync issues?