多线程应用程序中的显示任务必须使用原子锁或互斥锁吗?
Are atomics or mutex locks a must for display tasks in multi threading applications?
我正在使用 C++11 和内置线程 class std::thread
。使用 std::atomic
或 std::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" 的阅读,原子操作目前是昂贵的,但不是非常昂贵(比说,比遵循指向不在缓存中的内存地址的指针更便宜)。
我正在使用 C++11 和内置线程 class std::thread
。使用 std::atomic
或 std::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" 的阅读,原子操作目前是昂贵的,但不是非常昂贵(比说,比遵循指向不在缓存中的内存地址的指针更便宜)。