2015-12-06 57 views
0

本書說我們需要消除全局或靜態數據纔是線程安全的。我認爲線程安全意味着程序中沒有競爭條件。 但是,在以下示例中,爲了防止競爭條件,它將本地真正的「Point pt_ptr」從非指針類型更改爲指針類型「Point * pt_ptr」。我注意到他使用「malloc」,這意味着他將在堆中創建一些東西。堆中的東西被所有的線程共享......因爲它創建了共享的東西,它可以防止數據競爭,但它會是線程不安全的嗎?對C中的線程安全和競態條件感到困惑

int main(void) { 
 
    pthread_t tids[NUM_THREADS]; 
 
    int i; 
 
    Point *pt_ptr; 
 

 
    for (i= 0; i < NUM_THREADS; i++) { 
 
    pt_ptr= malloc(sizeof(*pt_ptr)); 
 
    pt_ptr->x= i; 
 
    pt_ptr->y= 3 * i + 2; 
 
    pthread_create(&tids[i], NULL, print_point, pt_ptr); 
 
    }

+0

所以,是的,內存是共享的,可以被所有線程看到。然而,重要的部分是如果該數據實際上是由多個線程訪問的。如果他們不是 - 沒有問題,如果你有多個線程訪問數據,可能會有問題。所以你需要多告訴我們一些。你的「因爲它創建了共享的東西,所以它阻止了數據競爭」似乎也是錯誤的。 – nos

+0

全局變量是共享內存的簡稱,但在這種情況下,pt_ptr不會被共享,它將爲每個線程分配一個新的私有內存。 – milevyo

回答

1

如果多於一個的線程試圖在沒有一些線程安全機制來訪問相同的內存空間(變量作爲一個例子),如互斥或旗語它只會被線程不安全的。它們用於提供阻塞機制,以便一個線程將坐下並「等待」,直到當前擁有的線程通過,此時第二個線程將具有訪問/修改該變量的能力。

將它們視爲DMV中的數字,您必須等到您的服務被調用後才能獲得服務。

+0

因爲for循環的每次迭代都會在指針pt_ptr的堆中創建一個新的內存空間,所以它是安全的,對吧? @ J.Murray – overloading

+0

你的例子是使用一個單線程,所以你的for循環語句一次只能執行一個。每次循環調用malloc()通過for語句實際上每次都會分配一個新的內存塊。所以,從本質上講,每次通過循環時,你都會使用一個全新的物品。 –

+1

非常感謝! – overloading

1

在這種情況下,循環的每次迭代調用malloc(),創建一個只傳遞給一個線程的新內存塊。 (正如J. Murray所指出的那樣。)這些動態變量根本不是全球性的。你可以代替寫:

int main(void) 
{ 
    pthread_t tids[NUM_THREADS]; 

    for (int i = 0; i < NUM_THREADS; i++) { 
    Point * const pt_ptr = malloc(sizeof(*pt_ptr)); 
    assert(pt_ptr); /* TODO: Handle the out-of-memory error. */ 
    pt_ptr->x= i; 
    pt_ptr->y= 3 * i + 2; 
    pthread_create(&tids[i], NULL, print_point, pt_ptr); 
    } 
    /* ... */ 
    return EXIT_SUCCESS; 
} 

該版本使這更清晰的pt_ptr每次迭代確實是一個獨立的局部變量。

+0

謝謝!!!!!! – overloading