并发std::call_once调用

Concurrent std::call_once calls

本文关键字:once 调用 call std 并发      更新时间:2023-10-16

请有人解释一下,为什么在执行两个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 << "1n";
        std::call_once(did_nothing, do_nothing);
        std::cout << "2n";
    }
    std::once_flag sleeped_longer;
    void sleep_longer()
    {
        std::this_thread::sleep_for(std::chrono::seconds(10));
    }
    void sleep_longer_once()
    {
        std::cout << "3n";
        std::call_once(sleeped_longer, sleep_longer);
        std::cout << "4n";
    }
}
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"answers"4"

很明显,这是一种不当行为。或者不是吗?

更新:我不能将其作为Visual Studio错误提交,因为我的工作帐户由于某种原因"无权提交此连接的反馈",不管这意味着什么。我收到了微软STL维护人员的回复,他希望在未来的某个时候调查这个问题。

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

它更喜欢行为不端
"对once_flag对象上的call_once的有效调用的完成与对同一once_flag对象上的所有后续调用同步。"(N3242,30.4.4.2类-3)。