我们怎么知道代码是线程安全的?

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_pixeldrawing.put_pixel 究竟做了什么,以及可能需要以什么顺序执行。

假设对put_pixel(c) 的调用顺序无关紧要(或者哪个线程进行调用),那么在这里删除临界区是安全的。如果需要严格的排序,我不确定关键部分是否是正确的解决方案。 (同样的规则显然适用于render_one_pixel,如果它改变了一些全局状态,当然也必须在“是否安全”中考虑到这一点)。

【讨论】:

以上是关于我们怎么知道代码是线程安全的?的主要内容,如果未能解决你的问题,请参考以下文章

如何知道 ruby​​ 中啥不是线程安全的?

Win32线程安全问题.同步函数

都说知道 HashMap 线程不安全,那它为啥就不安全?

线程安全的分析--finalstatic单例线程安全

怎么实现springMVC 多线程并发

什么是线程安全