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

时间:2013-11-19 14:58:46

标签: c++ thread-safety vtune

我正在关注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 () {}

};

1 个答案:

答案 0 :(得分:1)

如果没有修改全局状态(即,在此特定线程之外的状态),则某些事情是线程安全的。我们很难说出render_one_pixeldrawing.put_pixel实际上做了什么,以及它可能需要执行的顺序。

假设对put_pixel(c)的调用顺序无关紧要(或哪个线程进行调用),可以安全地删除此处的关键部分。如果需要严格的订购,我不确定关键部分是否是正确的解决方案。 (同样的规则明显适用于render_one_pixel,如果它改变某些全球状态,当然也必须在“它是安全的”中加以考虑。