首页 > 编程语言 >C++: std::once_flag 和 std::call_once

C++: std::once_flag 和 std::call_once

时间:2024-09-05 12:22:10浏览次数:6  
标签:std 函数 flag call 多线程 once

std::once_flag 和 std::call_once

std::once_flag 和 std::call_once 是 C++11 引入的同步原语,用于确保某个函数在多线程环境中只被执行一次。它们位于 头文件中,主要用于实现线程安全的初始化操作。

std::once_flag

概述

类型:std::once_flag 是一个结构体,用于记录某个函数是否已经被调用过。
用途:与 std::call_once 配合使用,确保某个函数在多线程环境中只被执行一次。

std::once_flag my_flag;

std::call_once

函数:std::call_once 是一个函数模板,用于确保某个函数在多线程环境中只被执行一次。

参数:
std::once_flag& flag:一个 std::once_flag 对象,用于记录函数是否已经被调用过。

Function&& f:要执行的函数或可调用对象。

Args&&… args:传递给函数的参数。

std::once_flag my_flag;

void initialize() {
    // 初始化代码
}

void some_function() {
    std::call_once(my_flag, initialize);
}

示例代码

以下是一个完整的示例,展示了如何使用 std::once_flag 和 std::call_once 来确保某个函数在多线程环境中只被执行一次:

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

std::once_flag my_flag;

void initialize() {
    std::cout << "Initialization code executed" << std::endl;
}

void thread_function() {
    std::call_once(my_flag, initialize);
}

int main() {
    std::thread t1(thread_function);
    std::thread t2(thread_function);
    std::thread t3(thread_function);

    t1.join();
    t2.join();
    t3.join();

    return 0;
}

底层实现

std::once_flag 和 std::call_once 的底层实现依赖于操作系统提供的同步机制,通常使用互斥锁(mutex)和条件变量(condition variable)来确保线程安全。

std::once_flag

std::once_flag 内部维护一个状态,用于记录函数是否已经被调用过。
这个状态通常是一个原子变量(atomic variable),确保在多线程环境下的操作是原子的。


std::call_once

std::call_once 内部使用一个互斥锁来保护对 std::once_flag 状态的访问。
如果函数尚未被调用,std::call_once 会锁定互斥锁,执行函数,然后更新 std::once_flag 的状态。
如果函数已经被调用,std::call_once 会立即返回,不会再次执行函数。

标签:std,函数,flag,call,多线程,once
From: https://blog.csdn.net/gopher9511/article/details/141905939

相关文章

  • 【Moveit2】MoveGroupInterface设置目标姿态,然后创建一个计划到该姿态的运动路径,stati
    PlanandExecuteusingMoveGroupInterface//CreatetheMoveItMoveGroupInterfaceusingmoveit::planning_interface::MoveGroupInterface;automove_group_interface=MoveGroupInterface(node,"panda_arm");//SetatargetPoseautoconsttarget_p......
  • 遥感影像-语义分割数据集:Postdam数据集详细介绍及训练样本处理流程
    原始数据集详情Potsdam数据集是一个有着2D语义分割内容标注的城市遥感数据集。KeyValue卫星类型未知覆盖区域一个典型的历史城市,有着大的建筑群、狭窄的街道和密集的聚落结构-Potsdam场景城市分辨率5cm数量38张单张尺寸6000*6000原始影像位深8位标签图片位深8位原始影像......
  • 【树莓派开发】gcc编译器中出现warning: #pragma once in main file
    众所周知,#pragmaonce语句是防止头文件重复包含非常常用的一条语句VS编译器在创建.h文件的时候会自动帮你在开头添加这个语句但是在gcc编译器下,这个语句就可能会出现一些问题所使用编译器:VS2019(windows10)树莓派(linux-gcc)warning:#pragmaonceinmainfile在我尝试在linux环境......
  • C++:std::thread 和 pthread
            在C++中,线程的实现主要有两种方式:使用C++11标准库中的std::thread和POSIX线程库(pthread)。这两种方式各有优缺点,适用于不同的场景。以下是对这两种方式的详细比较和示例代码。std::thread示例代码#include<iostream>#include<thread>#include<chrono>......
  • C++:std::this_thread::sleep_for 和 sleep
            在C++中,std::this_thread::sleep_for和sleep函数都可以用来使当前线程暂停执行一段时间,但它们有一些重要的区别。以下是对这两种方法的详细比较:std::this_thread::sleep_for定义:std::this_thread::sleep_for是C++11标准库中的一个函数,用于使当前线程暂停执......
  • stdio.h及字符串输入输出
    这里只简单介绍常用的C语言常见的输入输出及字符串的输入输出,可以作为常用C语言字符串的速记收藏。#include<stdio.h>scanf //与空格,tab键及换行就阻断缓冲区printf //格式输入输出gets(数组名) //直到遇到换行键停止chararr[n];gets(arr);puts(数组名) //......
  • gflags的使用
      C++gflags库使用说明_c++gflags使用-CSDN博客跨文件使用命令行参数  如果你想要访问在另一个文件定义的gflags变量呢?使用DECLARE_,它的作用就相当于用extern声明变量。为了方便的管理变量,我们推荐在.cc或者.cpp文件中DEFINE变量,然后只在对应.h中或者单......
  • Linux | Ubuntu 16.04.4 通过docker安装单机FastDFS
    Ubuntu16.04.4通过docker安装单机fastdfs前言很久没有写技术播客了,这是一件很不应该的事情,做完了事情应该有沉淀的。我先说一点前情提要,公司的fastdfs突然就挂了,做过的操作就是日志文件太大了,所以把日志文件给删了,理论上这个动作应该不影响程序运行才对。然后tracker怎么都......
  • 超详细教程 | Hands-On 基于 Flagchip FC4150 MCAL-使用 GPT 模块定时喂狗
    简介    本文将详细介绍如何使用EB工具配置FlagchipFC4150MCAL使用GPT模块定时喂狗,并重点强调了配置GPT、WDG模块的过程以及对GPT、WDG模块的详细解释,关于mcu、port、dio、icu、adc、pwm模块可参考之前发布的博文。本次示例演示将会使用FTU4_CH0超......
  • C++(std::cout 处理 char*)
    目录1.std::cout和char*2.std::cout处理nullptr情况3.数组与指针的区别4.特殊字符的处理5.总结在C++中,std::cout是标准输出流,通常用于将数据输出到控制台。在处理char*类型时,std::cout的行为与处理其他类型有所不同。1.std::cout和char*char*是一个指向字......