Моего приложение использует 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
контролировать некоторое поведение на второй поток который изменяет только на главном потоке.
ВОПРОС (ы):
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) {
...
}
Переменная должна быть определена как атомная переменная или вам необходимо заблокировать это, иначе вы получите неопределенное поведение из-за гонки данных. Определитель volatile делает ** не ** делает переменную атомной. – 2501
@ 2501, спасибо за комментарий. Я блокирую переменные с критическими разделами, когда меняю их. Как насчет '
Вам нужно будет узнать, что такое гонка данных. Ресурсы, доступные на этом веб-сайте. – 2501