2017-02-13 18 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 контролировать некоторое поведение на второй поток который изменяет только на главном потоке.

ВОПРОС (ы):

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, который вы уже сделали. Если переменная имела неатомный тип (например, map или даже просто 64-разрядное целое по 32-разрядной архитектуре), тогда вам понадобится блокировка.

: C & C++ стандарт не предполагает неделимость операций даже на простых операциях машинного слова, как чтение int, но если вы используете winapi, то вы на x86, что гарантирует его. (Итак, если вы хотите написать переносимый код, используйте блокировку, даже если вы пишете int в одном потоке и только читаете ее из других потоков.)

+0

Спасибо. Поэтому, если я правильно понимаю, если я использую 'volatile', я уверен, что блокирую только переменные, которые изменяются в одном потоке, независимо от того, используются ли они где-то в другом месте? _non-atomic_ - даже простые целые числа, такие как 'int32_t a;'? Я спрашиваю, потому что я также использую некоторый '' в _секундовом потоке_ (не меняя их в _секунном потоке_, просто прочитав), который я не могу установить как 'volatile'. Должен ли я заблокировать их перед тем, как использовать их, например, if (mymap ["bla"] == 0) ', потому что они не атомные? – user6096479

+0

.. или нужно заблокировать '' на _main thread_, когда я его модифицирую, прежде чем использовать его в _секунде thread_, так как он не атомный? – user6096479

+0

Да, конечно, как изменение, так и чтение карты очень далеки от атомной операции, поэтому она, безусловно, требует блокировки. –

 Смежные вопросы

  • Нет связанных вопросов^_^