2016-06-23 45 views
-1

我有一個問題,我無法解決。 我不得不做一個線程共享的數據結構,問題是: 線程是同時執行的,它們應該在特定的結構中插入數據,但每個對象都應該被插入互斥鎖中,因爲如果一個對象存在它不能重新插入。 我想過如果另一個線程想要放置相同的密鑰,它應該等待當前線程完成,那麼線程會放置它們正在工作的對象的鍵。 所以,換句話說,每一個線程執行此功能鎖定元素:C -Mutex數據結構與多線程

void lock_element(key_t key){ 
    pthread_mutex_lock(&mtx_array); 

    while(array_busy==1){ 
    pthread_cond_wait(&var_array,&mtx_array); 
    } 
    array_busy=1; 
    if((search_insert((int)key))==-1){ 
     // the element is present in array and i can't insert, 
     // and i must wait for the array to be freed. 
     // (i think that the problem is here) 
    } 
    array_busy=0; 
    pthread_cond_signal(&var_array); 
    pthread_mutex_unlock(&mtx_array); 
} 

後,我有我自由與後續的功能在ARRY重點對象完成:

void unlock_element(key_t key){ 

    pthread_mutex_lock(&mtx_array); 

    while(array_busy==1){ 
    pthread_cond_wait(&var_array,&mtx_array);      
    } 

    array_busy=1; 
    zeroed((int)key);          
    array_busy=0; 
    pthread_cond_signal(&var_array); 
    pthread_mutex_unlock(&mtx_array); 
} 

這樣,結果在每次執行中發生變化(例如:第一次程序插入300個對象,第二次插入100個對象)。

感謝您的幫助!

UPDATE:

@DavidSchwartz @Asthor我修改了代碼如下:

void lock_element(key_t key){ 
    pthread_mutex_lock(&mtx_array); 
    while((search_insert((int)key))==-1){ 
     //wait 
     pthread_cond_wait(&var_array,&mtx_array); 
    } 
    pthread_mutex_unlock(&mtx_array); 
} 

和...

void unlock_element(key_t key){ 
pthread_mutex_lock(&mtx_array); 

zeroed((int)key);         
pthread_cond_signal(&var_array); 
pthread_mutex_unlock(&mtx_array); 
    } 

但不是工作..它的行爲以同樣的方式像之前一樣。我也注意到函數search_insert(key)的奇怪行爲;

int search_insert(int key){ 
    int k=0; 
    int found=0; 
    int fre=-1; 
    while(k<7 && found==0){ 
    if(array[k]==key){ 
     found=1; 
    } else if(array[k]==-1) fre=k; 
    k++; 
    } 
    if (found==1) { 
    return -1; //we can't put the key in the array 

    }else { 
     if(fre==-1) exit(EXIT_FAILURE); 
     array[fre]=key; 
     return 0; 
    } 

    } 

永不熄滅的

if(found == 1) 
+1

當你已經在使用互斥鎖時,爲什麼你需要'array_busy'變量? – EOF

+0

爲什麼這是downvoted? – arunmoezhi

+0

互斥鎖(mtx_array)用於鎖定變量array_busy,只有在鎖定的情況下,我纔可以使用此變量。 – Flank

回答

0

你有幾個選項。

最簡單的選擇只是在整個操作過程中保持互斥鎖。除非您有強有力的證據表明您需要更高的併發性,否則您一定要選擇此選項。

通常,可以允許多個線程完成工作。此模式的工作原理如下:

  1. 獲取互斥量。
  2. 檢查對象是否在集合中。如果是這樣,請使用集合中的對象。
  3. 否則,釋放互斥鎖。
  4. 生成對象
  5. 再次獲取互斥鎖。
  6. 檢查對象是否在集合中。如果沒有,請添加它並使用您生成的對象。
  7. 否則,丟棄您生成的對象並使用集合中的對象。

這可能會導致兩個線程執行相同的工作。在您的用例中,這可能是不可接受的,因爲這是不可能的(某些工作只能完成一次),或者因爲併發性的增加不值得重複工作的成本。

如果沒有別的辦法,你可以用更復雜的解決方案去:

  1. 獲取互斥體。
  2. 檢查對象是否在集合中。如果是這樣,請使用集合中的對象。
  3. 檢查對象上是否有其他線程正在工作。如果是,請阻止條件變量並轉到步驟2.
  4. 指示我們正在處理該對象。
  5. 釋放互斥鎖。
  6. 生成對象。
  7. 獲取互斥量。
  8. 刪除我們正在處理對象的指示。
  9. 將對象添加到集合中。
  10. 廣播條件變量。
  11. 釋放互斥鎖。

這可以通過一個單獨的集合來實現,以跟蹤哪些對象正在進行中,或者您可以將特定版本的對象添加到包含指示正在進行的值的集合中。

0

答案是基於假設。

請考慮這種情況。你有2個線程試圖插入他們的對象。線程1和線程2都獲得索引爲0的對象。然後我們給出2個可能的場景。

答: 線程1啓動,抓住互斥鎖並繼續插入它們的對象。他們完成,讓下一個線程通過互斥體,這是2.線程1嘗試再次獲取互斥體以釋放索引,但在線程2擁有它時被阻塞。線程2嘗試插入它們的對象,但由於索引被佔用而失敗,所以插入從不發生。它釋放互斥鎖,線程1可以抓住它,釋放索引。然而,線程2已經嘗試並且未能插入它所具有的對象,這意味着我們只總共獲得1次插入。

B: 第二種情況。線程1啓動,獲取互斥鎖,插入對象,釋放互斥鎖。在線程2抓取它之前,線程1再次抓取它,清除索引並再次釋放互斥鎖。線程2然後成功地獲取互斥體,插入它釋放互斥體之前的對象。在這種情況下,我們得到2個插入。

最後,問題在於if語句內沒有任何反應,當一個線程無法插入一個對象和線程時,並沒有按照它的意思去做。這樣你的插入就比預期的要少。