2013-08-04 112 views
3

幾個星期前我有一堂課,我的解決方案很好,但是當觀察它更長時間時,我注意到了一些奇怪的行爲。 該練習使用兩個posix線程產生死鎖,然後解決它。 (我抽象的解決方案,因此它沒有任何不必要的代碼解決死鎖時的奇怪行爲

的場景如下:

  • 我有誰共享兩個虛構的資源兩個線程
  • 兩個線程啓動序列,然後設法佔領這兩個資源(按順序太)
  • 兩個線程都擁有佔領
  • 當一個線程都有他的作品持續5秒兩種資源不同的時間跨度,然後釋放該資源,並在他再次開始需要休息,當斷則試圖佔據這兩個資源
  • 每8秒功能checkes如果兩個線程都等待狀態(這兩個線程都一個資源,並等待第二次)
  • 死鎖時occures,誰的工作更線程得到取消,然後重新啓動

問題出在這裏,這取決於機器和編譯器標記輸出說,例如線程A被取消,但線程B啓動。我用不同的編譯器在不同的計算機上試過它,並使用不同的關係。 奇怪的是,我編譯gcc -Wall -Werror -ansi -pedantic -D_POSIX_C_SOURCE=200809L -pthread -lrt,並與第二死鎖問題occures,但是當我刪除-Wall和-Werror問題自帶的3僵局0O

我上傳的源here。編譯標誌位於源代碼中,我嘗試了gcc和clang。 我也試過Ubuntu 13.04和Arch。
Here是輸出,我用「 - >」標記了行

我忘記了一些東西,所以這個效果出現了嗎?我不認爲在某些庫中有錯誤。

+0

我沒有得到你同樣的效果。你可以發佈你看到的輸出嗎? –

回答

1

問題是你正在傳遞一個局部變量的地址給線程。而且這個局部變量在線程啓動時可能不再存在,並且您正在取消引用使用來保存局部變量但現在包含其他內容的地址位置。

由於它在程序的堆棧空間中,所以沒有收到段錯誤。

這裏是代碼的問題領域的一個亮點,它如何被引起的:

void resolve_deadlock() 
{ 
    void *pthread_exit_state; 
    int id_a = THREAD_A; 
    int id_b = THREAD_B; 

    <some code to detect deadlocks and kill a thread> 

/* restart the killed thread */ 
if (pthread_create(&threads[THREAD_B], NULL, &thread_function, (void *) &id_b) != 0) { 
        perror("Create THREAD_B\n"); 
        exit(EXIT_FAILURE); 
      } 
} 

因此程序運行和:

  1. resolve_deadlock叫
  2. 線X被殺害
  3. 在pthread_create被調用來創建一個線程
  4. resolve_deadlock函數結束
  5. 堆棧在旁邊函數調用
  6. 操作系統交換我們出去,並運行另一個線程
  7. 線程X運行,並取消引用不再存在我們的局部變量寫 - >未定義的行爲。
+0

所以我假設讓id_a和id_b全局解決錯誤?我可以發誓我昨天晚上試過,它仍然存在,但我現在再試一次,它似乎工作0(也許我昨天忘了一些事情) 但你有一個想法,爲什麼我得到不同的行爲,當我刪除 - 牆和 - 錯誤標誌?他們似乎只是設置編譯器輸出而不改變編譯。 – a2r

+0

還有沒有其他方式解決這個問題,而不是使變量全球? – a2r

+0

您看到的不同行爲是由於線程的計劃時間所致。如果你多次運行相同的編譯程序,那麼你會在不同的運行中看到錯誤(有時候本地var會存在,有時它不會)。 – dave