2017-02-13 49 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

是的,当然,修改和读取地图都不是一个原子操作,所以它肯定需要锁定。 –