Я написал программу для Windows на C ++, которая иногда использует два потока: один фоновый поток для выполнения трудоемкой работы;и еще один поток для управления графическим интерфейсом.Таким образом, программа по-прежнему реагирует на пользователя, что необходимо для возможности прервать определенную операцию.Потоки обмениваются данными через общую переменную bool
, которая устанавливается в true
, когда поток графического интерфейса сигнализирует рабочему потоку об отмене.Вот код, который реализует это поведение (я удалил нерелевантные части):
КОД, ВЫПОЛНЕННЫЙ ПОТОКОМ GUI
class ProgressBarDialog : protected Dialog {
/**
* This points to the variable which the worker thread reads to check if it
* should abort or not.
*/
bool volatile* threadParameterAbort_;
...
BOOL CALLBACK ProgressBarDialog::DialogProc( HWND dialog, UINT message,
WPARAM wParam, LPARAM lParam ) {
switch( message ) {
case WM_COMMAND :
switch ( LOWORD( wParam ) ) {
...
case IDCANCEL :
case IDC_BUTTON_CANCEL :
switch ( progressMode_ ) {
if ( confirmAbort() ) {
// This causes the worker thread to be aborted
*threadParameterAbort_ = true;
}
break;
}
return TRUE;
}
}
return FALSE;
}
...
};
КОД, ВЫПОЛНЕННЫЙ ПОТОКОМ РАБОТНИКА
class CsvFileHandler {
/**
* This points to the variable which is set by the GUI thread when this
* thread should abort its execution.
*/
bool volatile* threadParamAbort_;
...
ParseResult parseFile( ItemList* list ) {
ParseResult result;
...
while ( readLine( &line ) ) {
if ( ( threadParamAbort_ != NULL ) && *threadParamAbort_ ) {
break;
}
...
}
return result;
}
...
};
threadParameterAbort_
в обоих потоках указывает на переменную bool
, объявленную в структуре, которая передается рабочему потоку при создании.Он объявлен как
bool volatile abortExecution_;
Мой вопрос: мне нужно использовать здесь volatile
, и достаточно ли приведенного выше кода, чтобы обеспечить поточно-ориентированную программу?Я обосновал использование volatile
здесь (см. этот вопрос для фона), что он будет:
предотвратить чтение *threadParameterAbort_
использовать кеш и вместо этого получать значение из памяти, а
не позволяет компилятору удалить предложение if
в рабочем потоке из-за оптимизации.
(Следующий абзац касается только безопасности потоков программы как таковой, и не , повторяю, не подразумевает утверждение, что volatile
любым способом обеспечивает любые средства обеспечения безопасности потока.) Насколько я могу судить, он должен быть потокобезопасным, поскольку установка переменной bool
должна в большинстве, если не во всех, архитектурах быть атомарной операцией.Но я могу ошибаться.И меня также беспокоит, может ли компилятор изменить порядок инструкций, например, нарушить безопасность потоков.Но лучше быть в безопасности (не каламбур), чем сожалеть.
РЕДАКТИРОВАТЬ: Небольшая ошибка в моей формулировке заставила вопрос выглядеть так, как будто я спрашиваю, достаточно ли volatile
, чтобы обеспечить поток-Безопасность.Это не было моей целью - volatile
действительно никак не обеспечивает безопасность потока - но я хотел спросить, если приведенный выше код демонстрирует правильное поведение, гарантирующее, что программа является потокобезопасной.