多线程应用程序中的显示任务必须使用原子锁或互斥锁吗?

Are atomics or mutex locks a must for display tasks in multi threading applications?

我正在使用 C++11 和内置线程 class std::thread。使用 std::atomicstd::mutex 可以轻松同步数据,但我想知道 "non sensitive" 任务是否真的需要它 - 同时保持无错误的应用程序。假设有一个 class 比如

class FPS
{
  private:
    int rate;
  public:
    void change(const int i)
    {rate = i;}
    int read(void)
    {return rate;}
};

正在存储相机的帧率。在应用程序中,有一个线程用于读取帧速率的数据采集(帧抓取等),还有另一个线程处理显示帧速率的 GUI。本例显示为"non crucial",表示在某些情况下允许显示滞后于实际速率。 我当然可以简单地使用 atomic 来确保它的安全,但我仍然想知道它是否真的必须保证程序的无错误性能,假设应用程序在多核上运行 CPU .

C++ 线程模型对代码在 运行 时执行的操作非常宽松。您的特定 C++ 实现可能不像 C++ 允许的那样疯狂。

依赖它的问题是,如果它没有被记录和理解,你的编译器的下一个迭代版本可能会做出不同的假设,与 C++ 兼容,并破坏你的代码。

例如,如果您通过非同步 int 进行通信,编译器可能会注意到无法在此线程内修改数据。如果它可以证明这一点,那么可以将 int 存储在本地寄存器中并 忽略来自另一个线程的 int 的任何更新

更重要的是,一段代码可以从寄存器中读取它,另一段代码可以从内存中读取,并且您可以拥有不同的值。更重要的是,一次读取代码中的变量可能会变成两次读取,并且两次读取可能不一致:我们深陷未定义行为的领域。

所以不,这通常不安全。即使您的测试没有检测到任何问题,未在测试中显示的线程问题也非常常见:测试几乎永远不足以证明您的线程代码是安全的。

它在您的特定编译器和编译器版本以及编译器标志上可能是安全的。

http://en.cppreference.com/w/cpp/atomic/memory_order 介绍了如何做不到完整 atomics。请注意,并非所有 CPU 都会以不同方式处理这些情况,但存在区分所有这些情况的体系结构。我发现所有的内存顺序规则有点莫名其妙,因为我不习惯在它们都存在的系统上工作,但如果你真的需要性能,你可以考虑它。

根据我对 "performance cheat sheet" 的阅读,原子操作目前是昂贵的,但不是非常昂贵(比说,比遵循指向不在缓存中的内存地址的指针更便宜)。