2011-03-15 101 views
3

我正在創建一個使用雙緩衝的線程化應用程序,我試圖避免潛在的死鎖。主要思想是交換緩衝區線程鎖定寫入和讀取線程。然而,交換緩衝區線程很快,所以鎖不會長時間保持鎖定狀態。寫入和讀取線程較慢,但高效共享時間片(目標),因爲它們鎖定在不同的互斥鎖上。我的問題是這種設計有潛在的僵局嗎?C雙緩衝區實現死鎖?

  • 3線程...線程A,線程B,和C.螺紋
  • 2互斥...前互斥和後退的互斥。

  • 線程A填充後緩衝器
  • 線程B交換緩衝器。
  • 線程C使用前端緩衝區。

  • 線程A需要theBackMutex,填充後緩衝,釋放theBackMutex。
  • 線程C使用FrontMutex,使用前臺緩衝區,釋放FrontMutex。
  • 線程B需要theBackMutex,theFrontMutex,切換緩衝區,釋放theBackMutex,釋放theFront互斥

void *fill_back_buffer() { 
    while(1) { 
     if (0 != pthread_mutex_lock(&theBackMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     //should we get new data for back buffer? 
     pthread_cond_wait(&theBackBufferRefresh, &theBackMutex); 
     //fill back buffer 
     if (0 != pthread_mutex_unlock(&theBackMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     //hey we done filling the back buffer! 
     pthread_cond_signal(&theBackBufferFull); 
    } 
} 


void *swap_buffers() { 
    while(1) { 
     if (0 != pthread_mutex_lock(&theBackMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     if (0 != pthread_mutex_lock(&theFrontkMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     //do we have new data in the back buffer? 
     pthread_cond_wait(&theBackBufferFull, &theBackMutex); 

     //swap buffers 
     char* tmp; 
     tmp = theBufferAPtr; 
     theBufferAPtr = theBufferBPtr; 
     theBufferBPtr = tmp; 

     if (0 != pthread_mutex_unlock(&theFrontMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     if (0 != pthread_mutex_unlock(&theBackMutex)) { 
      perror("Mutex lock failed (!!):"); 
      exit(-1); 
     } 
     //hey please get more data! 
     pthread_cond_signal(&theBackBufferRefresh); 
     //hey you can use front buffer now! 
     pthread_cond_signal(&theBufferSwapped); 

    } 
} 

int main(int argc, char *argv[]) { 
    //initial fill of the back buffer 
    pthread_cond_signal(&theBackBufferRefresh); 
    while(1) { 
     if (0 != pthread_mutex_lock(&theFrontMutex)) { 
       perror("Mutex lock failed (!!):"); 
       exit(-1); 
     } 
     pthread_cond_wait(&theBufferSwapped, &theFrontMutex); 
     //use the front buffer and do stuff with it 
     if (0 != pthread_mutex_unlock(&theFrontMutex)) { 
       perror("Mutex lock failed (!!):"); 
       exit(-1); 
     } 
    } 
} 
+0

如果你不能工作,我們自己然後建立一個Petri網模型,並檢查它的方式。 – 2011-03-15 20:17:45

+0

我會檢查一下,我以前從未使用過Petri網模型。謝謝。 – 2011-03-15 20:27:36

+0

一旦你建立了你的模型,你可以將它導入到一個工具,並讓工具找到你的死鎖。漂亮的東西! – 2011-03-15 20:29:22

回答

2

條件變量應該用來表示某些(互斥鎖保護的)共享數據的狀態變化。你不能單獨使用它們。考慮一下如果一個線程在另一個線程等待這個條件之前發出一個條件,會發生什麼情況。

+0

啊,我現在看到了。我只在需要發信號並等待狀態改變時纔將它們用作信號。 – 2011-03-25 06:21:37

1

我沒有看到你創建的線程。我會假設你創建了線程。

swap_buffers()fill_back_buffer()確實包含經典的死鎖實現。當swap_buffers()正在等待theBackBufferFull時,它已鎖定theBackMutex。同時,fill_back_buffer()正在等待theBackMutex,然後它設置信號theBackBufferFull。因此,theBackBufferFull將永遠不會被髮信號,因爲theBackMutex不能被釋放。這是典型的死鎖情況。

+0

是的,我沒有包括整個代碼示例,只是想法。所以當2個線程試圖鎖定相同的互斥鎖時,會造成死鎖?我認爲它更聰明,只會阻止它最終跳出來。 – 2011-03-15 20:29:54

+0

你應該閱讀關於死鎖。這並不是說你有兩個線程鎖定同一個互斥鎖 - 問題是你有兩個線程阻塞相同的TWO同步原語,互斥鎖和信號,並且它們以相反的順序進行阻塞,導致死鎖。可以使用無死鎖的互斥鎖,但這不是你的問題。你有僵局嗎?是的,特別是我描述的地方。 – 2011-03-15 20:34:00

+0

我的理解是條件變量釋放它們的互斥量,所以我沒有看到你指的是死鎖。 – ninjalj 2011-03-15 21:10:52

0

儘量不使用額外的線程進行交換。

+0

是的,我想我可以添加交換到填充緩衝區線程。也許這會讓它變得更簡單。 – 2011-03-15 20:30:59

+0

這樣做有兩個線程的「正常」方式,但如果不以正確的順序鎖定,這將無濟於事。 – 2011-03-15 20:34:31