当前位置: 首页 > news >正文

C语言- 原子操作

基本概念

在C语言(尤其是C11标准之后)中,原子操作提供了一种机制,使得程序员可以在并发环境中,不使用互斥或其他同步原语,而直接对数据进行操作,同时确保数据的完整性和一致性。

原子变量和原子操作的核心思想是:无论什么时候,只有一个线程能够看到变量的修改操作。这种修改要么完全发生,要么完全不发生,没有中间状态。因此,这可以避免诸如“脏读”这样的并发问题。

原子类型

C11引入了<stdatomic.h>头文件,其中定义了各种原子类型,例如:

  • atomic_int
  • atomic_long
  • atomic_bool
    等等。

原子操作

对这些原子类型的变量进行操作时,可以使用以下原子操作函数:

  • atomic_store:原子存储值。
  • atomic_load:原子读取值。
  • atomic_fetch_add:原子增加。
  • atomic_fetch_sub:原子减少。
  • atomic_exchange:原子交换值。
  • atomic_compare_exchange_strongatomic_compare_exchange_weak:原子比较和交换。

这些操作确保在并发环境中,对原子变量的读取和修改是安全的。

内存顺序

为了实现高效的并发操作,现代硬件提供了各种各样的内存访问和指令执行的乱序(out-of-order)技术。这可能导致在不同的核或线程上观察到不同的指令和内存访问顺序。为了管理这种复杂性,<stdatomic.h>提供了不同的内存顺序选项:

  • memory_order_relaxed:放松的内存顺序,没有同步或顺序需求。
  • memory_order_acquire:在相关的原子操作前不会有内存重排序。
  • memory_order_release:在相关的原子操作后不会有内存重排序。
  • memory_order_acq_rel:同时具有acquire和release语义。
  • memory_order_seq_cst:为所有原子操作提供完整的序列一致性。

选择合适的内存顺序对于确保并发程序的正确性和性能至关重要。

总之,原子操作为C程序员提供了一种在高度并发的环境中对数据进行高效、安全操作的方法,无需使用复杂的同步原语。然而,正确和高效地使用原子操作需要对内存模型、内存顺序和硬件的实际行为有深入的了解。


原子类型

atomic_int

atomic_int 是 C11 和 C++11 标准库中提供的原子类型。它是专门为 int 类型设计的原子版本,用于在多线程环境中确保对 int 类型的变量进行的操作是原子的,从而避免数据竞争和其他相关的并发问题。

1. 定义:

在 C11 中,atomic_int 是一个原子整数类型。在 C++11 中,它被定义为 std::atomic<int>

2. 特性:

  • 原子性: 对 atomic_int 的操作(如递增、递减、存储和加载)是原子的,这意味着当一个线程对其进行操作时,其他线程不能同时对其进行操作。
  • 内存序: atomic_int 操作通常与特定的内存序关联,这些内存序定义了操作的可见性和顺序。例如,一个线程在某个 atomic_int 上执行的写操作何时对另一个线程可见。
  • 无锁: atomic_int 的实现通常是无锁的,尽管具体实现可能取决于平台和硬件支持。无锁实现通常比使用互斥锁或其他同步原语更高效。

3. 常见操作:

以下是可以在 atomic_int 上执行的一些原子操作:

  • load: 获取变量的当前值。
  • store: 设置变量的值。
  • fetch_add: 增加变量的值并返回旧值。
  • fetch_sub: 减少变量的值并返回旧值。
  • exchange: 设置变量的值并返回旧值。
  • compare_exchange_strongcompare_exchange_weak: 条件性地设置变量的值。

4. 示例:

#include <stdatomic.h>
#include <stdio.h>
#include <pthread.h>atomic_int counter = 0;void* increment(void* arg) {for (int i = 0; i < 1000; ++i) {atomic_fetch_add(&counter, 1);}return NULL;
}int main() {pthread_t threads[10];for (int i = 0; i < 10; i++) {pthread_create(&threads[i], NULL, increment, NULL);}for (int i = 0; i < 10; i++) {pthread_join(threads[i], NULL);}printf("Counter: %d\n", atomic_load(&counter));return 0;
}

在上述示例中,我们使用 atomic_int 作为计数器,启动了 10 个线程,每个线程都增加计数器 1000 次。使用 atomic_int 确保在并发环境中对计数器的所有操作都是原子的。

总之,atomic_int 是一种线程安全的整数类型,它提供了一系列原子操作,使得多个线程可以同时而安全地访问和修改其值,无需担心数据竞争或其他并发问题。

atomic_bool

atomic_bool 是 C11 和 C++11 标准库中提供的原子类型,专为布尔类型设计。这意味着在多线程环境下,对一个 atomic_bool 类型的变量进行的操作是原子性的,这在确保线程安全性和避免数据竞争时非常有价值。

1. 定义:

在 C11 中,atomic_bool 是一个原子布尔类型。在 C++11 中,它被定义为 std::atomic<bool>

2. 特性:

  • 原子性: 对 atomic_bool 的操作(如存储、加载、逻辑运算)是原子的。这意味着在任何给定时刻,只有一个线程可以对它进行操作,而其他线程不能看到该操作的中间状态。

  • 内存序: atomic_bool 提供了与特定的内存序关联的操作。这些内存序定义了操作的可见性和顺序,例如一个线程执行的写操作何时对另一个线程可见。

  • 无锁: 在大多数平台上,atomic_bool 的实现是无锁的。具体的实现可能会根据平台和硬件支持而变化,但无锁实现通常比使用互斥锁或其他同步原语更高效。

3. 常见操作:
以下是可以在 atomic_bool 上执行的一些原子操作:

  • load: 获取变量的当前值。
  • store: 设置变量的值。
  • exchange: 设置变量的值并返回旧值。
  • compare_exchange_strongcompare_exchange_weak: 条件性地设置变量的值。

4. 示例:

#include <stdatomic.h>
#include <stdio.h>
#include <pthread.h>atomic_bool flag = ATOMIC_VAR_INIT(false);void* set_flag(void* arg) {atomic_store(&flag, true);return NULL;
}int main() {pthread_t thread;pthread_create(&thread, NULL, set_flag, NULL);pthread_join(thread, NULL);bool is_set = atomic_load(&flag);printf("Flag is %s\n", is_set ? "set" : "not set");return 0;
}

在上述示例中,我们使用 atomic_bool 作为一个标志,并启动了一个线程来设置这个标志。使用 atomic_bool 确保了在并发环境中对标志的所有操作都是原子的。

总之,atomic_bool 提供了一个线程安全的方式来操作布尔变量,在并发编程中非常有用,特别是当需要确保对变量的操作是原子的时候。


原子操作

atomic_store

atomic_store 是C11标准中提供的一组原子操作函数,用于存储一个值到一个原子变量,确保这个操作是原子的,即在操作期间不会被其他线程中断。这种保证有助于防止在并发环境中出现数据竞争和不一致状态。

1. 声明:

原型为:

void atomic_store(volatile A *obj, C desired);

其中,

  • A 必须是原子类型。
  • obj 是要进行操作的原子对象的指针。
  • desired 是要存储到原子对象的值。

2. 描述:

atomic_storedesired 的值原子地存储到 *obj

相关文章:

C语言- 原子操作

基本概念 在C语言(尤其是C11标准之后)中,原子操作提供了一种机制,使得程序员可以在并发环境中,不使用互斥或其他同步原语,而直接对数据进行操作,同时确保数据的完整性和一致性。 原子变量和原子操作的核心思想是:无论什么时候,只有一个线程能够看到变量的修改操作。…...

设置hadoop+安装java环境

上一篇 http://t.csdnimg.cn/K3MFS 基本操作 接着上一篇 先导入之前导出的虚拟机 选择导出到对应的文件夹中 这里修改一下保存虚拟机的位置&#xff08;当然你默认也可以&#xff09; 改一个名字 新建一个share文件夹用来存放共享软件的文件夹 在虚拟机的设置中找到这个设置…...

阿里云新加坡主机服务器选择

阿里云新加坡主机有哪些选择&#xff1f;可以选择云服务器ECS或轻量应用服务器&#xff0c;都有新加坡地域可以选择&#xff0c;东南亚地区可以选择新加坡、韩国首尔、日本东京等地域&#xff0c;阿里云新加坡主机测试IP地址&#xff1a;161.117.118.93 可以测试下本地到新加坡…...

21天打卡掌握java基础操作

Java安装环境变量配置-day1 参考&#xff1a; https://www.runoob.com/w3cnote/windows10-java-setup.html 生成class文件 java21天打卡-day2 输入和输出 题目&#xff1a;设计一个程序&#xff0c;输入上次考试成绩&#xff08;int&#xff09;和本次考试成绩&#xff0…...

SQL题目记录

1.商品推荐题目 1.思路&#xff1a; 通过取差集 得出要推荐的商品差集的选取&#xff1a;except直接取差集 或者a left join b on where b null 2.知识点 1.except selectfriendship_info.user1_id as user_id,sku_id fromfriendship_infojoin favor_info on friendship_in…...

Linux程序调试器——gdb的使用

gdb的概述 GDB 全称“GNU symbolic debugger”&#xff0c;从名称上不难看出&#xff0c;它诞生于 GNU 计划&#xff08;同时诞生的还有 GCC、Emacs 等&#xff09;&#xff0c;是 Linux 下常用的程序调试器。发展至今&#xff0c;GDB 已经迭代了诸多个版本&#xff0c;当下的…...

前端打包项目上线-nginx

第一步&#xff1a;下载nginx。 直接下载 nginx/Windows-1.25.2 pgp 第二步&#xff1a;解压zip包 第三步&#xff1a;打开文件夹&#xff0c;把http里的路径打开cmd 第四步&#xff1a;打开你的http-server服务&#xff0c;没有下载去下一次就ok了 打开后就可以访问了 第五步…...

创龙瑞芯微RK3568参数修改(调试口波特率和rootfs文件)

前言 前面写了基本的文件编译、系统编译和系统烧写&#xff0c;差不多前期工作就准备的差不多了。目前的东西能解决大部分入门级的需求。当然如果需要开发的话&#xff0c;还需要修改其他东西&#xff0c;下面一步一步的给小伙伴介绍关键参数怎么修改。 给定波特率 拿到开发板…...

VMware——VMware17安装WindowServer2012R2环境(图解版)

目录 一、WindowServer2012R2镜像百度云下载二、安装 一、WindowServer2012R2镜像百度云下载 下载链接&#xff1a;https://pan.baidu.com/s/1TWnSRJTk0ruGNn4YinzIgA 提取码&#xff1a;e7u0 二、安装 打开虚拟机&#xff0c;点击【创建新的虚拟机】&#xff0c;如下图&…...

ModuleNotFoundError: No module named ‘torch‘

目录 情况1,真的没有安装pytorch情况2(安装了与CUDA不对应的pytorch版本导致无法识别出torch) 情况1,真的没有安装pytorch 虚拟环境里面真的是没有torch,这种情况就easy job了,点击此链接直接安装与CUDA对应的pytorch版本,CTRLF直接搜索对应CUDA版本即可查找到对应的命令.按图…...

采用Spring Boot框架开发的医院预约挂号系统3e3g0+vue+java

本医院预约挂号系统有管理员&#xff0c;医生和用户。管理员功能有个人中心&#xff0c;用户管理&#xff0c;医生管理&#xff0c;科室信息管理&#xff0c;预约挂号管理&#xff0c;用户投诉管理&#xff0c;投诉处理管理&#xff0c;通知公告管理&#xff0c;科室分类管理。…...

Jmeter性能测试(压力测试)

1.先保存 2.添加请求&#xff08;即添加一个线程组&#xff09; 3.添加取样器&#xff08;在线程组下面添加一个http请求&#xff09; 场景1&#xff1a;模拟半小时之内1000个用户访问服务器资源&#xff0c;要求平均响应时间在3000毫秒内&#xff0c;且错误率为0&#xff0…...

NetCore/Net8下使用Redis的分布式锁实现秒杀功能

目的 本文主要是使用NetCore/Net8加上Redis来实现一个简单的秒杀功能&#xff0c;学习Redis的分布式锁功能。 准备工作 1.Visual Studio 2022开发工具 2.Redis集群&#xff08;6个Redis实例&#xff0c;3主3从&#xff09;或者单个Redis实例也可以。 实现思路 1.秒杀开始…...

openGauss学习笔记-102 openGauss 数据库管理-管理数据库安全-客户端接入之查看数据库连接数

文章目录 openGauss学习笔记-102 openGauss 数据库管理-管理数据库安全-客户端接入之查看数据库连接数102.1 背景信息102.2 操作步骤 openGauss学习笔记-102 openGauss 数据库管理-管理数据库安全-客户端接入之查看数据库连接数 102.1 背景信息 当用户连接数达到上限后&#…...

lspci源码

lspci 显示Linux系统的pci设备最简单的方法就是使用lspci命令&#xff0c;前提是要安装pciutils包&#xff08;centos在最小化安装时不会自带该包&#xff0c;需要自己下载安装&#xff09; pciutils包的源码github地址为&#xff1a; https://github.com/pciutils/pciutils …...

CMake教程-第 8 步:添加自定义命令和生成文件

CMake教程-第 8 步&#xff1a;添加自定义命令和生成文件 1 CMake教程介绍2 学习步骤Step 1: A Basic Starting PointStep 2: Adding a LibraryStep 3: Adding Usage Requirements for a LibraryStep 4: Adding Generator ExpressionsStep 5: Installing and TestingStep 6: Ad…...

快速入门:Spring Cache

目录 一:Spring Cache简介 二:Spring Cache常用注解 2.1:EnableCaching 2.2: Cacheable 2.3:CachePut 2.4:CacheEvict 三:Spring Cache案例 3.1:先在pom.xml中引入两个依赖 3.2:案例 3.2.1:构建数据库表 3.2.2:构建User类 3.2.3:构建Controller mapper层代码 3.…...

探索音频传输系统:数字声音的无限可能 | 百能云芯

音频传输系统是一项关键的技术&#xff0c;已经在数字时代的各个领域中广泛应用&#xff0c;从音乐流媒体到电话通信&#xff0c;再到多媒体制作。本文将深入探讨音频传输系统的定义、工作原理以及在现代生活中的各种应用&#xff0c;以帮助您更好地了解这一重要技术。 音频传输…...

【C++】-c++的类型转换

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树&#x1f388; &#x1f389;作者宣言&#xff1a;认真写好每一篇博客&#x1f4a4; &#x1f38a;作者gitee:gitee✨ &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 动态规划算法&#x1f384; 如 果 你 …...

《论文阅读28》OGMM

一、论文 研究领域&#xff1a; 点云配准 | 有监督 部分重叠论文&#xff1a;Overlap-guided Gaussian Mixture Models for Point Cloud Registration WACV 2023 二、概述 概率3D点云配准方法在克服噪声、异常值和密度变化方面表现出有竞争力的性能。本文将点云对的配准问题…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器

第一章 引言&#xff1a;语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域&#xff0c;文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量&#xff0c;支撑着搜索引擎、推荐系统、…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

LLMs 系列实操科普(1)

写在前面&#xff1a; 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容&#xff0c;原视频时长 ~130 分钟&#xff0c;以实操演示主流的一些 LLMs 的使用&#xff0c;由于涉及到实操&#xff0c;实际上并不适合以文字整理&#xff0c;但还是决定尽量整理一份笔…...