我们怎么知道代码是线程安全的?
Posted
技术标签:
【中文标题】我们怎么知道代码是线程安全的?【英文标题】:How do we know that the code is thread safe? 【发布时间】:2013-11-19 14:58:45 【问题描述】:我正在关注this tutorial 以了解如何使用 VTUNE 移除锁 此页面在收集 Vtune 结果后显示以下内容:
识别最热门的代码行
点击热点导航按钮 转到等待时间最长的代码行。 VTune 放大器 突出显示第 170 行进入临界区 rgb_critical_section 在 draw_task 函数中。 draw_task 函数正在等待 几乎 27 秒,而这段代码行正在执行,并且大部分 处理器未被充分利用的时间。在此期间,关键 部分被竞争了 438 次。
rgb_critical 部分是应用程序所在的地方 序列化。每个线程都必须等待临界区 在它可以继续之前可用。只有一个线程可以在 一次关键部分。您需要优化代码以使其 更多并发。
在我进入下一部分之前,我能够按照本教程进行操作:Remove the Lock
解除锁定
引入 rgb_critical_section 是为了保护计算免受 多线程访问。简单分析一下,代码是线程的 安全且关键部分并不是真正需要的。
我的问题是我们如何知道代码是线程安全的?
正如建议的那样,我评论了那些行(EnterCritical... 和 LeaveCritical...),并看到了巨大的性能提升,但我不明白为什么不需要这个关键部分?哪项分析告诉我们这一点?
相关代码在analyze_locks.cpp中:
public:
void operator () (const tbb::blocked_range <int> &r) const
unsigned int serial = 1;
unsigned int mboxsize = sizeof(unsigned int)*(max_objectid() + 20);
unsigned int * local_mbox = (unsigned int *) alloca(mboxsize);
memset(local_mbox,0,mboxsize);
for (int y=r.begin(); y!=r.end(); ++y)
drawing_area drawing(startx, totaly-y, stopx-startx, 1);
// Enter Critical Section to protect pixel calculation from multithreaded access (Needed?)
// EnterCriticalSection(&rgb_critical_section);
for (int x = startx; x < stopx; x++)
color_t c = render_one_pixel (x, y, local_mbox, serial, startx, stopx, starty, stopy);
drawing.put_pixel(c);
// Exit from the critical section
// LeaveCriticalSection(&rgb_critical_section);
if(!video->next_frame()) tbb::task::self().cancel_group_execution();
draw_task ()
;
【问题讨论】:
问题是任何内存是否一次被多个线程访问。 人们不能“简单地”推理线程安全。例如,在此处使用 OpenMP 时,逐步分析此代码以消除数据竞争 - viva64.com/en/b/0035/print 【参考方案1】:如果没有全局状态(即该特定线程之外的状态)被修改,则某些东西是线程安全的。我们很难说出render_one_pixel
和drawing.put_pixel
究竟做了什么,以及可能需要以什么顺序执行。
假设对put_pixel(c)
的调用顺序无关紧要(或者哪个线程进行调用),那么在这里删除临界区是安全的。如果需要严格的排序,我不确定关键部分是否是正确的解决方案。 (同样的规则显然适用于render_one_pixel
,如果它改变了一些全局状态,当然也必须在“是否安全”中考虑到这一点)。
【讨论】:
以上是关于我们怎么知道代码是线程安全的?的主要内容,如果未能解决你的问题,请参考以下文章