欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

谈谈C++的volatile关键字以及常见的误解

程序员文章站 2022-04-14 23:14:12
近期看到C++标准中对volatile关键字的定义,发现和java的volatile关键字完全不一样,C++的volatile对并发编程基本没有帮助。网上也看到很多关于volatile的误解,于是决定写这篇文章详细解释一下volatile的作用到底是什么。 ......
转载请保留以下声明
  作者:。)

按照C++标准,这是volatile唯一的功能,但是在一些编译器(如,MSVC)中,volatile还有线程同步的功能,但这就是编译器自己的拓展了,并不能跨平台应用。

对volatile常见的误解

实际上“volatile可以在线程间同步”也是比较常见的误解。比如以下的例子:

class AObject
{
public:
    void wait()
    {
        m_flag = false;
        while (!m_flag)
        {
            this_thread::sleep(1000ms);
        }
    }
    void notify()
    {
        m_flag = true;
    }

private:
    volatile bool m_flag;
};

AObject obj;

...

// Thread 1
...
obj.wait();
...

// Thread 2
...
obj.notify();
...

对volatile有误解的人,或者对并发编程不了解的人可能会觉得这段逻辑没什么问题,可能会认为volatile保证了,wait()对m_flag的读取,notify()对m_flag的写入,所以Thread 1能够正常醒来。实际上并不是,Thread 1可能永远看不到m_flag变成true。因为在多核CPU中,每个CPU都有自己的缓存。缓存中存有一部分内存中的数据,CPU要对内存读取与存储的时候都会先去操作缓存,而不会直接对内存进行操作。所以多个CPU“看到”的内存中的数据是不一样的,这个叫做内存可见性问题(memory visibility)。并发编程下,一个程序可以有多个线程在不同的CPU核中同时运行,这个时候内存可见性就会影响程序的正确性。放到例子中就是,Thread 2修改了m_flag对应的内存,但是Thread 1在其他CPU核上运行,而两个CPU缓存和内存没有做同步,导致Thread 1运行的核上看到的一直都是旧的数据,于是Thread 1永远都不能醒来。内存可见性问题不是多线程环境下会遇到的唯一的问题,CPU的乱序执行也会导致一些意想不到的事情发生,关于这点volatile能做的也是有限的。这些都是属于并发编程的内容,在此我就不多做展开,总之volatile关键字对并发编程基本是没有帮助的。

那么用不了volatile,我们该怎么修改上面的例子?C++11开始有一个很好用的库,那就是atomic类模板,在<atomic>头文件中,多个线程对atomic对象进行访问是安全的。以下为修改后的代码:

class AObject
{
public:
    void wait()
    {
        m_flag = false;
        while (!m_flag)
        {
            this_thread::sleep(1000ms);
        }
    }
    void notify()
    {
        m_flag = true;
    }

private:
    atomic<bool> m_flag;
};

只要把“volatile bool”替换为“atomic<bool>”就可以。<atomic>头文件也定义了若干常用的别名,例如“atomic<bool>”就可以替换为“atomic_bool”。atomic模板重载了常用的运算符,所以atomic<bool>使用起来和普通的bool变量差别不大。一些atomic的高级用法,由于要涉及到C++的内存模型与并发编程,我就不在此展开了,以后有时间再补上。

(0)
打赏 谈谈C++的volatile关键字以及常见的误解 微信扫一扫

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

谈谈C++的volatile关键字以及常见的误解
验证码: 谈谈C++的volatile关键字以及常见的误解