在这个多线程C ++代码中是否需要“volatile”? [英] Is 'volatile' needed in this multi-threaded C++ code?

查看:117
本文介绍了在这个多线程C ++代码中是否需要“volatile”?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在C ++中编写了一个Windows程序,它有时使用两个线程:一个后台线程用于执行耗时的工作;以及用于管理图形界面的另一线程。这样,程序仍然响应于用户,需要能够中止某个操作。线程通过共享的 bool 变量进行通信,当GUI线程发信号通知工作线程中止时,变量设置为 true 。下面是实现这种行为的代码(我已经去掉了不相关的部分):

I've written a Windows program in C++ which at times uses two threads: one background thread for performing time-consuming work; and another thread for managing the graphical interface. This way the program is still responsive to the user, which is needed to be able to abort a certain operation. The threads communicate via a shared bool variable, which is set to true when the GUI thread signals the worker thread to abort. Here is the code which implements this behaviour (I've stripped away irrelevant parts):


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;
    }

    ...

};



由工人执行的代码



CODE EXECUTED BY THE WORKER THREAD


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 _ code> bool 在创建时传递给工作线程的结构中声明的变量。它被声明为

threadParameterAbort_ in both threads point to a bool variable declared in a structure which is passed to the worker thread upon creation. It is declared as

bool volatile abortExecution_;

我的问题是:我需要在这里使用 volatile ,这是足够的代码,是线程安全的?我推理为使用 volatile 的理由(见这个问题的背景)是:

My question is: do I need to use volatile here, and is the code above sufficient to ensure that the program is thread-safe? The way I've reasoned for justifying the use of volatile here (see this question for background) is that it will:


  • 阻止读取 * threadParameterAbort _ 以使用缓存,而是从内存中获取值

  • prevent the reading of *threadParameterAbort_ to use the cache and instead get the value from memory, and

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

prevent the compiler from removing the if clause in the worker thread due to optimization.

(以下段落仅涉及程序的线程安全性,并且,我重复,声明 volatile 以任何方式提供了任何确保线程安全的方法。)就我所知,它应该是线程安全的设置为 bool 变量应该在大多数(如果不是全部)体系结构是一个原子操作。但我可能是错的。我也担心编译器是否可能重新排序指令,如断开线程安全。

(The following paragraph is only concerned with the thread-safety of the program as such and does not, I repeat, does not involve claiming that volatile in any way provides any means of ensuring thread-safety.) As far as I can tell, it should be thread-safe as setting of a bool variable should in most, if not all, architectures be an atomic operation. But I could be wrong. And I'm also worried about if the compiler may reorder instructions such as to break thread-safety. But better be safe (no pun intended) than sorry.

编辑:
我的文字中的一个小错误使问题出现好像我在问: volatile 是否足以确保线程安全。这不是我的意图 - volatile 确实不以任何方式确保线程安全 - 但我的意思是如果上面提供的代码展示正确的行为

A minor mistake in my wording made the question appear as if I was asking if volatile is enough to ensure thread-safety. This was not my intent -- volatile does indeed not ensure thread-safety in any way -- but what I meant to ask was if the code provided above exhibit the correct behaviour to ensure that the program is thread-safe.

推荐答案

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

You should not depend on volatile to guarantee thread safety, this is because even though the compiler will guarantee that the the variable is always read from memory (and not a register cache), in multi-processor environments a memory barrier will also be required.

使用正确的锁围绕共享内存。锁像一个关键部分通常是非常轻量级的,在没有争用的情况下可能会被所有实现useride。它们还将包含必要的内存屏障。

Rather use the correct lock around the shared memory. Locks like a Critical Section are often extremely lightweight and in a case of no contention will probably be all implemented userside. They will also contain the necessary memory barriers.

Volatile只能用于内存映射的IO,其中多次读取可能返回不同的值。类似地,对于内存映射写入。

Volatile should only be used for memory mapped IO where multiple reads may return different values. Similarly for memory mapped writes.

这篇关于在这个多线程C ++代码中是否需要“volatile”?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆