c++ - 此多线程 C++ 代码中是否需要 'volatile'?

标签 c++ multithreading volatile

我用 C++ 编写了一个 Windows 程序,它有时使用两个线程:一个后台线程用于执行耗时的工作;和另一个用于管理图形界面的线程。这样程序仍然响应用户,这是能够中止某个操作所必需的。线程通过共享的 bool 变量进行通信,当 GUI 线程向工作线程发出信号以中止时,该变量设置为 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 的理由(参见 this question 了解背景)是它将:

  • 防止读取 *threadParameterAbort_ 以使用缓存,而是从内存中获取值,并且

  • 防止编译器因优化而删除工作线程中的 if 子句。

(以下段落仅关注程序本身的线程安全,,我重复一遍,涉及声明 volatile 以任何方式提供确保线程安全的任何方法。)据我所知,它应该是线程安全的,因为 bool 变量的设置应该在大多数情况下(如果不是全部的话) ,架构是一个原子操作。但我可能是错的。而且我还担心编译器是否会重新排序指令,例如破坏线程安全。但最好是安全(没有双关语意)而不是抱歉。

编辑: 我措辞中的一个小错误使这个问题看起来好像我在问 volatile 是否足以确保线程安全。这不是我的意图——volatile 确实不能以任何方式确保线程安全——但我想问的是上面提供的代码是否表现出正确的行为以确保程序是线程的-安全。

最佳答案

你不应该依赖 volatile 来保证线程安全,这是因为即使编译器会保证变量总是从内存中读取(而不是寄存器缓存),在多处理器环境中内存屏障也会被要求。

而是在共享内存周围使用正确的锁。像关键部分这样的锁通常非常轻量级,在没有争用的情况下可能会全部在用户端实现。它们还将包含必要的内存屏障。

Volatile 应该只用于多次读取可能返回不同值的内存映射 IO。内存映射写入也是如此。

关于c++ - 此多线程 C++ 代码中是否需要 'volatile'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3612505/

相关文章:

java - 当我在项目中使用 volatile 时,为什么下面的代码显示不同的结果?

有人可以解释以下代码语句吗?

c++ - vector 排序只是用自定义比较器反转输入

c++ - 如何以编程方式获取 QTableWidgetItem 的边距宽度?

java - 同步之前更新内存?

c# - 现有文件部分的锁定检查

java - 为什么 AbstractOwnableSynchronizer.exclusiveOwnerThread 没有声明为 volatile?

c++ - vector 中的指针问题

c# - 无法将 uchar ptr 转换为 opencvsharp

C89:使用 rand_r() 的多线程随机值