2017-02-13 78 views
-1

我的應用程序使用CreateThread創建輔助(只)線程來執行每10ms,像下面Win32線程

map<string, int32_t> a_map; 

DWORD WINAPI Table::manual_action_execute_thread(LPVOID lpParameter) { 
    while(Table::manual_action_execute_thread_run) { 
     ... 
     if (!Table::automatic_action_execute_inprogress) { 
     ... 
     } 
     ... 
     if (a_map["blah"] == 0) { 
     ... 
     } 
     ... 
     Sleep(10); 
    } 
    return 0; 
} 

的變量聲明如下:

static volatile bool manual_action_execute_thread_run; 
static volatile bool automatic_action_execute_inprogress; 

在開始我的線程之前,第一個取值爲true,所以我不使用鎖定。第一個需要false

我使用::automatic_action_execute_inprogress來控制秒線程其中只有主線程上改變一些行爲。

問題(S):

1)因爲我只在主線程更新::automatic_action_execute_inprogress,只是讀它秒線程我還需要首先使用EnterCriticalSection鎖呢?或者鎖定僅限於在兩個線程上更改的共享變量?

2)那麼<map>用在多個線程上,並且只用一個修改呢?當然,我必須鎖定它EnterCriticalSection每當變化,但如何read訪問?我是否應該鎖定它當我從它讀取(如if (a_map["foo"] == 0))如果可以改變,甚至通過一個單一的線程?像這樣的例子?

EnterCriticalSection(&cs); 
    bool val = a_map["foo"]; 
LeaveCriticalSection(&cs); 

    if (val == 0) { 
     ... 
    } 
+0

變量必須定義爲原子變量,否則您需要鎖定它,否則你會得到未定義的行爲,由於數據競賽。限定符volatile不會**使可變原子。 – 2501

+0

@ 2501,感謝您的評論。當我改變它們時,我將關鍵部分的變量鎖定。那麼在多個線程上使用「」並且只用一個修改呢?我應該鎖定它,每當更改或我應該鎖定每一個_read_,因爲它是非原子? – user6096479

+0

您將不得不瞭解數據競賽是什麼。本網站提供的資源。 – 2501

回答

-4

因爲只在一個線程中更新變量,只是讀它在其他線程,因爲變量的類型是原子,你不需要任何鎖定機制。你需要做的就是聲明volatile,你已經完成了。如果變量屬於非原子類型(例如,在32位體系結構中爲map或者甚至只是一個64位整數),那麼您需要鎖定。

的C & C++標準並不假定甚至喜歡閱讀的int簡單的機器字操作操作的原子,但如果你正在使用winapi那麼你就x86,這保證了它。 (因此,如果要編寫便攜式代碼,即使您正在一個線程上編寫int並僅從其他線程讀取它,也要使用鎖定。)

+0

謝謝。所以,如果我理解正確,如果我使用'volatile',我可以安全地鎖定只在一個線程上更改的變量,無論他們在其他地方使用嗎? _non-atomic_甚至是簡單的整數,比如'int32_t a;'?我在問,因爲我在_secondary thread_中使用了一些''(不會在第二個線程中更改它們,只是讀取它),我不能將它們設置爲volatile。我應該在使用它們之前將它們鎖定,比如'if(mymap [「bla」] == 0)'因爲它們是非原子的嗎? – user6096479

+0

..或需要鎖定_main thread_上的''當我修改它之前在_second thread_上使用它,因爲它是非原子的? – user6096479

+0

是的,當然,修改和讀取地圖都不是一個原子操作,所以它肯定需要鎖定。 –