2013-06-26 71 views
1

我在求職面試中遇到了這個問題,對於我的生活我找不到答案(他們最終沒有告訴你答案,因爲這是一個書面測試):找不到死鎖

int thread2_finished = 0; 

void t1() { 
    printf("t1 is running\n"); 
    while (!thread2_finished) { usleep(50); } 
    printf("t2 is doing stuff\n");  
} 


void t2() { 
    printf("t2 is running\n"); 
    sleep(5); 
    printf("t2 woke up\n");  
    thread2_finished = 1; 
    printf("t2 finished\n"); 
} 

我們所知道的是,大多數它的工作時間 - 但有時線程1永遠存在(不打印的最後一條消息),而線程2 確實打印他的所有消息 - 這怎麼可能?

我猜我錯過這裏一些基本的東西,但我唯一能想到的是,這個問題是與高速緩存 - 像T1裝載值(0),並對其進行緩存,然後立即T2的值爲1,但由於一些奇怪的原因,T1將繼續使用舊的緩存值,但這對我來說似乎很奇怪。

+0

問題是? – carlito

+0

問題是(也是編輯後) - 當thread1處於某種死鎖狀態時,thread2如何完成? –

+1

'volatile'? 't1()'可能不知道't2()'已經改變了'thread2_finished'的值。如果兩個線程在不同的CPU內核上運行,我想這可能會發生。 – Kane

回答

1

這樣寫的代碼看起來是正確的(而且是邏輯方式),但是如果使用真實環境它不能正常工作,修復將是關鍵字易失性但是原因有點複雜因爲這個關鍵字的行爲會改變每種語言/編譯器,因此這裏正確的answer

1

您不能保證t1在t2運行時已經啓動。 sleep不適用於正確的線程同步。

有人也可能認爲thread2_finished應該是不穩定的。實際上這應該不重要,因爲編譯器不知道usleep的作用,因此不能認爲usleep不會改變全局變量。另一方面,在許多體系結構中,您需要擁有更好的同步性,而不僅僅是更新全局變量。在另一個線程(如果運行在不同的cpu上)可能很久沒有看到全局變量的更新值,而在其他線程上(如果不是緩存一致),它可能永遠不會看到它。操作系統中的鎖定原語應該提供足夠的邏輯來確保其他線程可以看到來自一個線程的副作用。

總之 - 即使這可以在大多數情況下工作,永遠不要這樣做。使用適當的鎖定,條件變量和信號量。