2017-05-25 98 views
0

下面是我的代碼,其中兩個變量在回調時更新,每50ms調用一次。還有一個讀取器線程每隔50ms喚醒一次並讀取變量。併發讀寫

經過this後,我猜想會有一些情況,讀取的線程會在收到回調時喚醒,因爲我在讀寫時沒有鎖定相同的互斥量,在這種情況下,它會導致讀取的內存不一致。

但是,當我運行它時,這種情況永遠不會發生。是不是已經運行了足夠長的時間,還是在我的理解中有錯誤?

recursive_mutex mutex1 
recursive_mutex mutex2 
var1, var2 

//called every 50ms 
onUpdateListener() { 
    lock(mutex1) 
    update var1 
    update var2 
} 

VarReaderThread::readVar() { 
    sleep(50) 
    while(true) { 
     { 
     lock(mutex2) 
     read var1 
     read var2 
     sleep(50) 
     } 
    } 
} 
+0

你的互斥體的'範圍'不清楚。 –

+1

爲什麼要使用這些互斥鎖?是否有其他代碼訪問變量?因爲在這種情況下,它們完全沒用。 –

+0

您不應該同時書寫和閱讀,否則可能會遇到不一致的狀態(競爭條件)。儘管可以同時執行讀取和讀取,但您不應該同時寫入和寫入。寫作不混合。使用單獨的鎖進行讀取和寫入將無濟於事。正如@HenkHolterman在那段代碼中暗示那些互斥體什麼都不做。 – Persixty

回答

0

數據爭用,當兩個或更多個線程訪問共享數據,其中其中至少一個是其中一個或多個線程可能會遇到不一致的狀態的寫入操作發生。

提供的代碼有兩個互斥體,一個用於讀取,一個用於寫入。 這不會排除一個線程讀取共享數據(例子中的var1,var2),而另一個寫入它們,或者更準確地說,在一個線程開始寫入其中的一個之後並且在某個情況下完成寫入另一個之前其中該中間狀態將被視爲代碼邏輯及其目的的參數內的不一致狀態。

需要一個mutex使閱讀和寫作獨家。另外,還不清楚爲什麼遞歸互斥體已經被聲明。只有當一個給定的線程可能遇到要求它獲得它已經擁有的互斥體的代碼時,才需要這樣做。在可能的情況下設計和編碼這種情況會更好。已被引入

顯式unlock步驟,這可以或可以不被明確地根據編碼模型所需(在C需要,使用用C++ std::lock_guard或​​或在Java中finally,等等)。

已引入一些條件來指示正確的終止條件。 while(true)是壞習慣,除非其他條件會優雅地終止它。

更復雜的模型可能會使用'共享互斥',其中多個線程可以在'讀'模式下保存它,但只有一個保持'寫'模式。這可能需要或不需要某些信號來確保'寫入'不會進入活鎖,許多讀者無休止地阻止'寫入'訪問。

mutex mutex_v1_v2 //The mutex controlling shared state var1, var2. 
var1, var2 

//called every 50ms 
onUpdateListener() { 
    lock(mutex_v1_v2) 
    update var1 
    update var2 
    unlock(mutex_v1_v2) 
} 

VarReaderThread::readVar() { 
    sleep(50) 
    while(!finished) { 
     lock(mutex_v1_v2) 
     read var1 
     read var2 
     unlock(mutex_v1_v2) 
     sleep(50) //V. V. important to sleep not holding the mutex! 
    } 
}