c++ 中的多线程线程安全动画建议

Posted

技术标签:

【中文标题】c++ 中的多线程线程安全动画建议【英文标题】:Multithreaded thread-safe animation suggestions in c++ 【发布时间】:2011-06-07 08:28:29 【问题描述】:

我有一个基于计时器的动画程序,它计划在工作线程中运行。该程序旨在在启动时始终运行。我还有一个图像制作线程,负责图像处理,然后将每个处理后的图像(JPEG/PNG 格式)提供给动画线程以参与图像循环,无需用户干预。 这是一个典型的基于内存的图像循环程序。也就是说,所有用户选择的图像都预先加载到RAM中。我使用地图容器来管理图像序列,以 std::map 的格式声明,它将 Key 类型的图像文件名与 Data 类型的 CBitmap 指针相关联。我还使用向量字符串(声明为 std::vector)以与上述映射键列表相对应的排序顺序保存图像文件列表的副本,以便按顺序编号迭代每个图像。这可能没有必要。 关于动画控制,允许以下类似信息亭的操作(一些伴随着各自的变量声明):

bool m_bPlay;   // Play forward
bool m_bPause; // Pause animation
bool m_bStop;  // Stop animation
bool m_bReverse; // Play backward
bool m_bRepeat; // Repeated play when reaching to last image
DWORD m_dwFrom;  // Starting image number
DWORD m_dwTo;    // Ending image number
DWORD m_dwCurrent;  // Current image number
DWORD m_dwFPS;   // Frames per second

其中 m_dwTo 变量可以由用户通过使用嵌入在主 GUI 窗口顶部的工具栏中的旋转按钮来更改,或者每次将新处理的图像添加到上述地图中时由应用程序自动增加以及矢量容器。同样,m_dwFrom 变量也可以像 m_dwTo 一样手动更改,或者根据用户定义的滚动存档配置(例如,保持3 天内的图像),同时应从上述地图和矢量容器中删除过期图像。用户可以在图像循环过程中随时更改 m_dwFPS 变量,并在主 GUI 窗口顶部的工具栏中嵌入一个下拉列表框。 感谢您花时间阅读我想做的长篇解释。我希望它可以帮助您回答我的以下问题:

    为了使 m_dwFrom、m_dwTo、m_dwCurrent 和 m_dwFPS 线程安全,使用 InterlockedExchange 或 InterlockedCompareExchange 是否比使用其他锁(如 CriticalSection、Mutex 等)更有效率和性能提升? 如何使 std::map 和 std::vector 线程安全?仅使用传统锁,还是与编译器重新排序屏障(例如,Visual C++ 的 _ReadWriteBarrier)和/或 CPU 重新排序屏障(例如 MemoryBarrier x86 和 x64 CPU 系列)更好地结合使用?

我期待看到您的建议。高度赞赏代码或错误代码 sn-ps。提前谢谢! 金李

【问题讨论】:

对不起,我会重复我的第二个问题:2。如何使 std::map<:string cbitmap> 和 std::vector<:string> 线程安全?仅使用传统锁,还是与编译器重新排序屏障(例如,Visual C++ 的 _ReadWriteBarrier)和/或 CPU 重新排序屏障(例如 MemoryBarrier x86 和 x64 CPU 系列)更好地结合使用? 【参考方案1】:

我可能错了,但据我从您的描述中猜到,我会使用传统的锁和互斥锁来使您的共享向量和映射以及其他共享变量线程安全。这只是最直接的方法,而且您的方案听起来并不需要大量性能来证明任何更复杂的事情是合理的。如果分析表明传统锁定成为性能问题,我只会触及任何更花哨的东西!

如何使 std::map 和 std::vector 线程安全?

执行此操作的常用方法是简单地围绕您需要访问的容器函数编写一个锁定包装器。例如:

class myAnimationManager
private:
std::map<std::string, CBitmap*> m_imagesMap;
Mutex m_mutex;

public:
CBitmap * getImageByName(const std::string & _name)

ScopedLock l(m_mutex); //lock image map access
return m_imagesMaps[_name];

//...
;

使用标准锁定原语的好处不仅在于简单,而且在使用 boost::thread 时具有可移植性。

【讨论】:

感谢 moka 对我 Q2 的回复。我去年完成了我的简单动画项目。但它在一年的 7X24 运行中多次崩溃。我的动画存储库 std::map<:string cbitmap> 可能是导致应用程序关闭的最可疑对象。所以,这是我在 SO 上提出的第二个问题的主要目的。顺便说一句,我使用 CriticalSection 来防止动画帧读/写竞争条件。

以上是关于c++ 中的多线程线程安全动画建议的主要内容,如果未能解决你的问题,请参考以下文章

C++中的多线程实现

Servlet的多线程和线程安全

java的多线程:线程安全问题

C++ Static变量跨平台多线程安全性分析

JAVA中的多线程

说说java中的多线程