并发std :: call_once调用

时间:2014-10-21 00:22:48

标签: c++ c++11

可以请有人解释一下为什么在执行两个std::call_once调用之前,此程序中的两个线程(使用Visual Studio 2012/2013附带的编译器编译时)都会被阻止?另一个Visual Studio错误(假设它在使用GCC编译时表现如预期)?有人可以想出一个解决方法吗?想象一下我所经历的所有痛苦,以解决问题,并请,怜悯。

#include <chrono>
#include <iostream>
#include <mutex>
#include <thread>

namespace
{
    std::once_flag did_nothing;

    void do_nothing()
    { }

    void sleep_shorter_and_do_nothing_once()
    {
        std::this_thread::sleep_for(std::chrono::seconds(3));
        std::cout << "1\n";
        std::call_once(did_nothing, do_nothing);
        std::cout << "2\n";
    }

    std::once_flag sleeped_longer;

    void sleep_longer()
    {
        std::this_thread::sleep_for(std::chrono::seconds(10));
    }

    void sleep_longer_once()
    {
        std::cout << "3\n";
        std::call_once(sleeped_longer, sleep_longer);
        std::cout << "4\n";
    }
}

int main()
{
    std::thread t1(sleep_shorter_and_do_nothing_once);
    std::thread t2(sleep_longer_once);
    t1.join();
    t2.join();
    return 0;
}

详细说明,使用GCC编译时,它的行为符合预期:

  • 打印“3”,
  • 等待3秒,
  • 打印“1”,
  • 立即打印“2”,
  • 再等6-7秒,
  • 并打印“4”。

使用Visual Studio 2012/2013附带的编译器进行编译时,其行为如下:

  • 打印“3”,
  • 等待3秒,
  • 打印“1”,
  • 等待另外6-7秒
  • 然后立即打印“2”和“4”
显然,这是一种不当行为。或者不是吗?

更新:我无法将此提交为Visual Studio错误,因为我的工作帐户由于某种原因“无权提交此连接的反馈”,无论这意味着什么。我收到了微软STL维护者的回复,说他希望将来某个时候调查这个问题。

2 个答案:

答案 0 :(得分:2)

我得到了微软STL维护人员的回复,称在Visual Studio 2015中修复了这个问题。

答案 1 :(得分:0)

它更喜欢不当行为。
&#34;对once_flag对象上的call_once的有效调用的完成与相同的once_flag 对象上的call_once的所有后续调用同步。&#34; (N3242,30.4.4.2-第3条)。