2011-03-19 49 views
1

我正在嘗試執行粗線程中斷。這部分代碼是否需要互斥鎖?

'interruptRequested'變量正在被頻繁檢查。在操作系統課上,我們學到了飢餓 - 在這裏或類似的情況下可能嗎?我知道示例程序的行爲與我在運行時的預期相同,但它可能只是一種僥倖。

下面是我在做什麼的簡化版本:

//Compile with -lpthread 

#include <iostream> 
#include <signal.h> 
#include <sys/types.h> 
#include <time.h> 
#include <unistd.h> 
#include <pthread.h> 

using namespace std; 

bool interruptRequested; 
pthread_mutex_t spamMutex; 
void *Spam(void *); 

int main(int argc, char *argv[]) 
{ 

pthread_t tid; 

interruptRequested = false; 

unsigned long long int timeStarted = time(NULL); 
pthread_create(&tid, NULL, Spam, NULL); 
unsigned long long int difference = 0; 


while (true) 
{ 
    pthread_yield(); 
    difference = (time(NULL) - timeStarted); 
    if (difference >= 5)//Spam the terminal for 5 seconds 
    { 
     //while (pthread_mutex_trylock(&spamMutex)); 
     interruptRequested = true; 
     //pthread_mutex_unlock(&spamMutex); 
     break; 
    } 


} 

return 0; 
} 

void *Spam (void *arg) 
{ 
while (true) 
{ 
    //while (pthread_mutex_trylock(&spamMutex)); 
    if (interruptRequested == true) 
    { 
     //pthread_mutex_unlock(&spamMutex); 
     break; 
    } 
    //pthread_mutex_unlock(&spamMutex); 
    cout << "I'm an ugly elf" << endl; 
    pthread_yield(); 
} 

interruptRequested = false; 
pthread_exit (0); 
} 

其實,在真正的代碼,我不使用的時間差的方式。我的程序將從服務器收到一條消息,此時我需要中斷該線程。

回答

0

是的,你必須首先使用互斥來保護讀取和寫入interruptRequested,在各塊。

即使會出現它按預期方式工作,實際上也可能沒有。軟件不能接受99%的成功率。同樣,你的測試程序是微不足道的 - 在現實世界中它會(默默地或神祕地)失敗的機會是很好的。

使用volatile(或原子,在很多情況下)作爲鎖的替代是不好的想法。這種模式最終會失敗,雖然它往往出現在輕負載下正常工作。有幾個角落的情況下,但你應該放棄揮發性的協會是替代正確的設計,使用鎖定。實際上你可以通過使interruptRequestedint並僅使用遞增/遞減來測試。在重負載下 - 您可以快速超過[0 ... 1]。

你會經常使用揮發性和/或原子公司的聲明時/讀/寫interruptRequested(再次,我建議一個int/INC/DEC /邊界檢查,尤其是在你學習)。如果讀取和寫入都被鎖定(在這種情況下應該是這樣),使用原子讀取/寫入將無濟於事。

關於你的程序,條件(pthread_cond_t)可能是一個不錯的選擇。

1

書面,該代碼並不一定保證能工作,因爲編譯器可能會優化掉在檢查interruptRequested工作線程內,因爲它從來沒有的功能裏面寫。這意味着生成的代碼可能只有一個while (true)循環(或者與之相當的東西)。

爲了防止這種情況發生,您需要確保編譯器識別出該變量可能在其他地方被修改過。你可以通過標記interruptRequestedvolatile來做到這一點,它向編譯器表明它不應該被優化掉。使用互斥鎖也是一個好主意,因爲大多數編譯器都足夠聰明,可以認識到使用互斥鎖表示互斥體內引用的變量可能會在外部修改。

+0

+1是的,使用volatile屬性是一個好主意 – fabrizioM 2011-03-19 20:16:09

0

我認爲一般共享數據應該用互斥鎖來處理。

在這種特定情況下,只有一個線程更新控制變量,所以它可能使用互斥鎖太多。您可以在幾毫秒的主動循環中進行時間休眠,以使主循環時常激活。