【问题标题】:Concurrent std::call_once calls并发 std::call_once 调用
【发布时间】:2014-10-21 00:22:48
【问题描述】:

请有人解释一下为什么这个程序中的两个线程(使用 Visual Studio 2012/2013 附带的编译器编译时)在两个 std::call_once 调用都被执行之前都被阻塞了?另一个 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 错误提交,因为我的工作帐户由于某种原因“无权为此连接提交反馈”,无论这意味着什么。我收到了 Microsoft STL 维护人员的回复,说他希望在未来的某个时间调查这个问题。

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    我收到了来自 Microsoft 的 STL 维护人员的回复,称该错误已在 Visual Studio 2015 中修复。

    【讨论】:

    • 如果它是您答案的公开回复链接
    • @UmNyobe 对不起,这是一封电子邮件。无论如何,那是很久以前的事了。而且我显然不应该在我的旧问题中修复语法/格式,因为它出于某种原因刺激了很多新的 cmets!
    • 在 VS2015 发行说明中提到,在 DevDiv#1092852 下:blogs.msdn.microsoft.com/vcblog/2015/07/14/…
    【解决方案2】:

    它更喜欢成为一种不当行为。
    “对 once_flag 对象的 call_once 的有效调用的完成与对 同一个 once_flag 对象的所有后续 call_once 调用同步。” (N3242, 30.4.4.2-clause-3)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-09
      • 1970-01-01
      • 1970-01-01
      • 2014-06-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多