2015-07-06 57 views
0

我有一個對象列表,可添加到,從中刪除,並且恐龍本身需要被提供。這一切都發生在高度多線程的環境中,因此列表受到互斥鎖保護。互斥模式,其中多個線程可以只讀訪問

static Mutex s_dinosaurMutex; 
static vector<Dinosaur> s_dinosaurList; 

void AddDinosaur(const Dinosaur& dinosaur) 
{ 
    s_dinosaurMutex.Lock(); 
    s_dinosaurList.push_back(dinosaur); 
    s_dinosaurMutex.Unlock(); 
} 

void RemoveDinosaur(const Dinosaur& dinosaur) 
{ 
    s_dinosaurMutex.Lock(); 

    vector<IMadderReceiver*>::iterator it = find(s_dinosaurList.begin(), s_dinosaurList.end(), dinosaur); 
    if (it != s_dinosaurList.end()) 
     s_dinosaurList.erase(it); 

    s_dinosaurMutex.Unlock(); 
} 

void FeedDinosaur(const Dinosaur& dinosaur) 
{ 
    s_dinosaurMutex.Lock(); 

    vector<IMadderReceiver*>::iterator it = find(s_dinosaurList.begin(), s_dinosaurList.end(), dinosaur); 
    if (it != s_dinosaurList.end()) 
     (*it).Feed(); // Feeding a dinosaur can take a long time, ~ 1 second 

    s_dinosaurMutex.Unlock(); 
} 

現在的問題是在餵養。這可能需要很長時間,但如果多個線程同時餵食同一個(或不同的)恐龍,那絕對沒問題。餵食過程因此不應該阻止其他FeedDinosaur調用,儘管它應該停止添加和刪除調用,並等待這些調用完成。目前的行爲是,許多線程排隊排隊,以餵養恐龍,這使得系統癱瘓。

是否有一種特殊的(類似互斥體的)設計模式,允許需要只讀訪問權限的正常線程的這種類型的行爲?

+1

是的,這是「讀寫器鎖」的用途。 – Sneftel

+1

除了@Sneftel提到的內容之外,我還建議在''std :: lock_guard''之類的互斥量周圍使用RAII封裝,以確保在函數的每個退出路徑上釋放互斥對象 – Alejandro

+0

[Reader/Writer Locks在C + +](http://stackoverflow.com/questions/244316/reader-writer-locks-in-c) – ecatmur

回答

3

這是一個讀寫器互斥; Boost和C++使用更通用的術語「共享互斥體」,因爲它可以用於除多個讀寫器之外的模式。

Boost.Thread從版本1.35.0(Reader/Writer Locks in C++)開始有shared_mutex。自C++ 14開始,C++有shared_timed_mutex,並且在C++ 17中有shared_mutex;直到可用,您可以使用C++ 14 shared_timed_mutex,而不使用超時機制。

在您的編寫器線程中,鎖定共享互斥體唯一訪問權限(使用unique_lock);在您的讀者線程中,鎖定共享互斥體共享訪問權限(使用shared_lock)。

+0

優秀的答案,謝謝。除了使用Boost之外,是否碰巧有C++ 11的替代方案? – Yellow

+1

@Yellow它會很難正確和高效地實現 - 請參閱http://stackoverflow.com/questions/12033188/how-would-a-readers-writer-lock-be-implemented-in-c11 – ecatmur