std::call_once 是阻塞调用吗?

2023-11-25

我在用着std::call_once在我的代码中仅初始化一些共享变量一次。调用代码位于由多个线程触发的回调内。 我有兴趣知道,因为我在文档中找不到它是否std::call_once本质上是阻塞的,就好像有一个std::lock_guard反而? 实际情况看起来确实如此。

例如,将打印以下内容"Done"在任何之前print()将被称为:

#include <future>
#include <iostream>
#include <thread>
#include <mutex>

std::once_flag flag;

void print()
{
    for(int i=0;i<10;i++)
    {
          std::cout << "Hi, my name is " << std::this_thread::get_id() 
            << ", what?" << std::endl;
    }
}

void do_once()
{
    std::cout << "sleeping for a while..." << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << "Done" << std::endl;
}

void work()
{
    std::call_once(flag, [](){ do_once(); });
    print();
}


int main()
{
    auto handle1 = std::async(std::launch::async, work);
    auto handle2 = std::async(std::launch::async, work);
    auto handle3 = std::async(std::launch::async, work);
    auto handle4 = std::async(std::launch::async, work);

    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}

我假设确实如此(因为我不知道如何以其他方式实现它),但是这种行为是否得到保证,或者是否有编译器决定std::call_once确实会被调用一次,但允许其他线程继续并忽略此调用?


Yes std::call_once是一个阻塞调用。从 [thread.once.callonce] 我们有

Effects:执行 call_once 但不调用其func是一种被动的执行。调用它的 call_once 的执行func是主动执行。主动执行应调用INVOKE (DECAY_COPY ( std::forward<Callable>(func)), DECAY_COPY (std::forward<Args>(args))...)。如果这样的 func 调用抛出异常,则执行异常,否则返回。异常执行应将异常传播给 call_once 的调用者。在所有处决中call_once对于任何给定的once_flag:至多一次应为返回处决;如果有返回 执行,它应该是最后一个活跃的执行;仅当有返回执行时才会有被动执行。[注意:被动执行允许其他线程可靠地观察较早返回的执行产生的结果。 ——尾注]

同步:对于任意给定的once_flag:所有活动执行均按总顺序发生;活动执行的完成与 (1.10) 总顺序中下一个执行的开始同步;并且返回的执行与所有被动执行的返回同步。

emphasis mine

这意味着所有调用call_once将等到函数传递给call_once完成。在你的情况下,这意味着do_once()必须在任何线程调用之前调用print()

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

std::call_once 是阻塞调用吗? 的相关文章

随机推荐

  • 正则表达式匹配单个新行。正则表达式匹配双新行

    我正在尝试构建一个正则表达式来匹配一个单独的换行符 n 同样 我需要另一个正则表达式来匹配双换行符 n n 不属于较长的换行符 例如 n n n or n n n n n n etc n n and n n n 匹配太多 它们匹配较长换行符
  • 使用 Linq to GroupBy 和 Sum 数据表

    你好 我有一个这样的数据表 Id Amount 1 Amount 2 Amount 3 1 2 2 2 12 4 6 4 12 6 6 5 22 7 2 1 22 7 2 2 我需要像这样获取我的数据表 Id
  • 使用 CSS font-family 选择不适用于 Android 的 Droid 字体

    我发现以下 HTML 代码在 Android 上不起作用 它只会使用默认字体 Droid Sans 在桌面上它可以按预期工作 p style font family none v nd whisky i tequila pre fix p
  • 使用/ jQuery 滚动到特定元素

    我有一个很长的嵌套 div 列表 我在查询字符串上传递特定元素 实际上是段落元素 的 ID 并打开其 div 和父级 onload 但是 列表太长 有时打开的元素隐藏在窗口底部下方 如何自动滚动用户的浏览器窗口以使显示的元素位于屏幕顶部 您
  • JavaScript 中的有效属性名称、属性分配和访问

    更新的问题 到底什么才是 Javascript 中有效的属性名称 各种财产分配方式有何不同 属性名称如何影响属性访问 Note 我最初问题的答案 见下文 有助于澄清一些事情 但也带来了新的麻烦 现在我有机会更加熟悉 JavaScript 我
  • 如何备份和恢复 Delphi 设置? [复制]

    这个问题在这里已经有答案了 可能的重复 如何迁移 Delphi 或克隆 Delphi 注册表设置 我很快需要格式化我的电脑 但我已经按照我想要的方式完美设置了 IDE 和环境设置 以及我安装的一些组件 显然 格式化并重新安装 Windows
  • ASP.NET MVC 中控制器的内置基类:Controller 还是 ControllerBase?

    ASP NET MVC 中控制器的内置基类是什么 System Web Mvc Controller 还是 System Web Mvc ControllerBase 在谷歌搜索后我不清楚 On ASP NET 控制器是从 System W
  • asp.net core mvc 密码验证器

    在asp net core MVC中自定义密码验证规则的简单方法是什么 这个问题就像有人在这里遇到的一样如何更改 ASP Net MVC Identity 2 中的密码验证 唯一的区别是我正在使用asp net核心MVC 最新版本 使用 V
  • 交互式输入标题,并使用捕获在其下放置条目

    使用如下所示的捕获模板 我可以将条目添加到文件中的不同标题中 如何在捕获期间手动输入标题 而不是像我现在所做的那样将每个标题设置为 emacs 文件中的一个键 setq org capture templates l Log entry f
  • 有没有办法将 matplotlib 图旋转 45 度?

    我正在寻找一种方法 将 matplotlib pyplot Python 库 中生成的绘图旋转 45 度 例如 这样您就可以得到菱形而不是正方形 有人知道这是否可以做到吗 我能想到的一种方法是对所有数据使用旋转过滤器 使其看起来旋转 但绘图
  • 列表视图中的单选按钮

    我在列表视图格式中显示刺痛列表 我使用默认列表视图并使用放置了一个单选按钮simple list item single choice 但这在右侧显示了单选按钮 我想在左侧显示单选按钮 是否可以使用默认列表视图在左侧显示单选按钮 simpl
  • 实现Hadoop的Writable接口的枚举值

    假设我有一个枚举 public enum SomeEnumType implements Writable A 0 B 1 private int value private SomeEnumType int value this valu
  • selectedIndex 在回发期间丢失 - ASP.NET

    我有一个列表框控件
  • iOS 在提交应用程序之前链接到应用程序商店

    我正在为我的 iPhone 应用程序构建一个 关于 控制器 我看到其他应用程序成功地将 市场价格 链接包含在其 关于 控制器中 我是否可以预测我的链接是什么 以便我可以在应用程序的第一个版本中对其进行硬编码 而不是上传 找出链接 发布更新
  • 元刷新重定向到顶部框架

    我有以下代码 Body of this page 这是行不通的 我用谷歌搜索了这个并得出了相同的结论 这应该有效 但事实并非如此 任何人都可以帮我解决
  • 如何在 Rails 中构建由多个模型组成的 JSON 响应

    一 想要的结果 I have User and Item楷模 我想构建一个如下所示的 JSON 响应 user username Bob foo whatever bar hello items id 1 name one zim plan
  • 在 JavaScript 中加入 2 个“线程”

    如果我有一个 ajax 调用关闭获取 通过回调 然后同时运行一些其他代码 当前两个函数完成后 我怎样才能有第三个函数被调用 我确信轮询很容易 setTimeout 然后检查一些变量 但我宁愿回调 是否可以 您可以为 AJAX 调用和同时运行
  • 你能将冒泡排序表述为幺半群或半群吗?

    给出以下冒泡排序的伪代码 procedure bubbleSort A list of sortable items repeat swapped false for i 1 to length A 1 inclusive do if th
  • OutputCache VaryByCustom cookie 值

    有没有办法根据 cookie 值设置 OutputCache 的值 为了简单起见 这是我的方法 OutputCache Duration 600 VaryByParam None VaryByCustom ztest public View
  • std::call_once 是阻塞调用吗?

    我在用着std call once在我的代码中仅初始化一些共享变量一次 调用代码位于由多个线程触发的回调内 我有兴趣知道 因为我在文档中找不到它是否std call once本质上是阻塞的 就好像有一个std lock guard反而 实际