实现C语言的原子操作

什么是原子操作呢?即操作本身无法再被划分为更细的步骤。我们一般都是在多线程环境中,才会需要原子操作的支持。因为当多个线程中对共享资源进行原子操作时,编译器和 CPU 将能够保证这些操作的正确执行。原子操作就是说同一时刻只会有一个线程在操作共享资源。当该线程将整个原子操作全部执行完毕后,其他线程才可以继续执行同样的操作。

C11 提供了 stdatomic.h 的头文件,可以方便地使用原子操作能力。与原子操作相关的常用C标准库函数:

  • atomic_flag_test_and_set : 将一个atomic_flag的值设置为真,并返回旧值
  • atomic_flag_clear:将一个atomic_flag的值设值为假
  • atomic_init:初始化g个已经存在的原子对象
  • atomic_fetch_add_explicit:原子加法
  • atomic_is_lock_free:检查指定对象是否是lock-free的
  • atomic_exchange:原子地交换两个值
  • atomic_compare_exchange_weak:比较并原子地交换两个值(允许失败)
  • atomic_compare_exchange_strong:比较并原子地交换两个值
  • atomic_signal_fence:在线程和信号处理之间建立内存栅栏
  • atomic_thread_fence:在线程之间建立内存栅栏
#include <threads.h>
#include <stdio.h>
#include <stdatomic.h>#define THREAD_COUNT 10
#define THREAD_LOOP 100000000#ifndef __STDC_NO_ATOMICS__ // 判断编译器是否对原子操作提供支持
_Atomic long counter = 0; // 原子类型的全局变量,线程们的共享资源
#endifint run(void *arg){for(int i = 0; i < THREAD_LOOP; i++){atomic_fetch_add_explicit(&counter,1,memory_order_relaxed);//使用原子加法}printf("Thread %d terminates.\n",*((int*)arg));return thrd_success;
}int main(void){
#if !defined(__STDC_NO_THREADS__) || !defined(__STDC_NO_ATOMICS__)int ids[THREAD_COUNT];thrd_t threads[THREAD_COUNT];for(int i = 0; i < THREAD_COUNT; i++){ids[i] = i+1;thrd_create(&threads[i],run,ids+i);//创建线程}for(int i = 0; i < THREAD_COUNT; i++){thrd_join(threads[i],NULL);//等待线程执行完成}printf("Counter value is: %ld.\n",counter);
#endifreturn 0;
}
~/Desktop$ gcc atomic.c -o atomic
~/Desktop$ ./atomic
Thread 9 terminates.
Thread 10 terminates.
Thread 2 terminates.
Thread 3 terminates.
Thread 7 terminates.
Thread 4 terminates.
Thread 5 terminates.
Thread 8 terminates.
Thread 6 terminates.
Thread 1 terminates.
Counter value is: 1000000000.

_AtomicC11 新引入的 关键字,修饰全局变量 counter,将它定义为一个原子类型,也可以使用C 标准库为我们封装好的宏 atomic_long来声明。
atomic_fetch_add_explicit 函数来完成对 counter 变量的累加过程,使线程在进行数据累加时独占整个变量。该函数的第三个参数指定当前操作需要满足的内存顺序。编译器和处理器可能会采用指令重排来优化程序的运行效率,当在多核 CPU 上运行存在线程间数据依赖的多线程应用时,程序的正确性可能会出现问题。可以通过指定各个原子操作的具体内存顺序来解决这个问题。内存顺序枚举值用途:

  • memory_order_relaxed:对执行顺序不做任何保证,编译器和处理器可以按照需求进行适当的优化。
  • memory_order_release:必须完成所有之前的写操作,才能执行本条写操作
  • memory_order_acquire:所有后续的读操作,必须在本条执令完成后才能执行

与使用互斥量相比,原子操作可以更加清晰和方便地抽象并行代码,而不需要频繁进行加锁与释放锁的操作。从性能角度来看,原子操作的执行通常直接依赖于 CPU 提供的相应的原子机器指令。而使用互斥量则需要让线程阻塞,还要频繁进行上下文切换,比较之下,原子操作的性能一般会更好。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/68894.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

何谓共赢?

A和B是人或组织&#xff0c;他们怎样的合作才是共赢呢&#xff1f; 形态1:A提供自己的身份证等个人信息&#xff0c;B用来作贷款等一些事务&#xff0c;A每月得到一笔钱。 A的风险远大于收益&#xff0c;或者B从事的是非法行为&#xff1b; 形态2:A单方面提前终止了与B的合作…

物联网 STM32【源代码形式-使用以太网】连接OneNet IOT从云产品开发到底层MQTT实现,APP控制 【保姆级零基础搭建】

物联网&#xff08;IoT&#xff09;‌是指通过各种信息传感器、射频识别技术、全球定位系统、红外感应器等装置与技术&#xff0c;实时采集并连接任何需要监控、连接、互动的物体或过程&#xff0c;实现对物品和过程的智能化感知、识别和管理。物联网的核心功能包括数据采集与监…

Redis|前言

文章目录 什么是 Redis&#xff1f;Redis 主流功能与应用 什么是 Redis&#xff1f; Redis&#xff0c;Remote Dictionary Server&#xff08;远程字典服务器&#xff09;。Redis 是完全开源的&#xff0c;使用 ANSIC 语言编写&#xff0c;遵守 BSD 协议&#xff0c;是一个高性…

架构技能(四):需求分析

需求分析&#xff0c;即分析需求&#xff0c;分析软件用户需要解决的问题。 需求分析的下一环节是软件的整体架构设计&#xff0c;需求是输入&#xff0c;架构是输出&#xff0c;需求决定了架构。 决定架构的是软件的所有需求吗&#xff1f;肯定不是&#xff0c;真正决定架构…

Linux:线程池和单例模式

一、普通线程池 1.1 线程池概念 线程池&#xff1a;一种线程使用模式。线程过多会带来调度开销&#xff0c;进而影响缓存局部性和整体性能。而线程池维护着多个线程&#xff0c;等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价&…

maven mysql jdk nvm node npm 环境安装

安装JDK 1.8 11 环境 maven环境安装 打开网站 下载 下载zip格式 解压 自己创建一个maven库 以后在idea 使用maven时候重新设置一下 这三个地方分别设置 这时候maven才算设置好 nvm 管理 npm nodejs nvm下载 安装 Releases coreybutler/nvm-windows GitHub 一键安装且若有…

【B站保姆级视频教程:Jetson配置YOLOv11环境(六)PyTorchTorchvision安装】

Jetson配置YOLOv11环境&#xff08;6&#xff09;PyTorch&Torchvision安装 文章目录 1. 安装PyTorch1.1安装依赖项1.2 下载torch wheel 安装包1.3 安装 2. 安装torchvisiion2.1 安装依赖2.2 编译安装torchvision2.2.1 Torchvisiion版本选择2.2.2 下载torchvisiion到Downloa…

【算法-位运算】位运算遍历 LogTick 算法

文章目录 1. 引入2. LogTick 优化遍历过程3. 题目3.1 LeetCode3097 或值至少为 K 的最短子数组 II3.2 LeetCode2411 按位或最大的最小子数组长度3.3 LeetCode3209 子数组按位与值为 K 的数目3.4 LeetCode3171 找到按位或最接近 K 的子数组3.5 LeetCode1521 找到最接近目标值的函…

NLP深度学习 DAY5:Sequence-to-sequence 模型详解

Seq2Seq&#xff08;Sequence-to-Sequence&#xff09;模型是一种用于处理输入和输出均为序列任务的深度学习模型。它最初被设计用于机器翻译&#xff0c;但后来广泛应用于其他任务&#xff0c;如文本摘要、对话系统、语音识别、问答系统等。 核心思想 Seq2Seq 模型的目标是将…

吴恩达深度学习——优化神经网络

本文来自https://www.bilibili.com/video/BV1FT4y1E74V&#xff0c;仅为本人学习所用。 文章目录 优化样本大小mini-batch 优化梯度下降法动量梯度下降法指数加权平均概念偏差纠正 动量梯度下降法 RMSpropAdam优化算法 优化学习率局部最优问题&#xff08;了解&#xff09; 优…

Shell篇-字符串处理

目录 1.变量引用 2.获取字符串长度 3.字符串截取 4.删除子字符串 5.字符串替换 总结&#xff1a; Bash&#xff08;Shell 脚本&#xff09;中的字符串处理语法。以下是对其的介绍和总结&#xff1a;Bash 变量可以使用不同的语法来获取、修改和删除字符串的内容。图片中列…

CMake项目编译与开源项目目录结构

Cmake 使用简单方便&#xff0c;可以跨平台构建项目编译环境&#xff0c;尤其比直接写makefile简单&#xff0c;可以通过简单的Cmake生成负责的Makefile文件。 如果没有使用cmake进行编译&#xff0c;需要如下命令&#xff1a;&#xff08;以muduo库echo服务器为例&#xff09;…

书生大模型实战营7

文章目录 L1——基础岛提示词工程实践什么是Prompt(提示词)什么是提示工程提示设计框架CRISPECO-STAR LangGPT结构化提示词LangGPT结构编写技巧构建全局思维链保持上下文语义一致性有机结合其他 Prompt 技巧 常用的提示词模块 浦语提示词工程实践(LangGPT版)自动化生成LangGPT提…

Shadow DOM举例

这东西具有隔离效果&#xff0c;对于一些插件需要append一些div倒是不错的选择 <!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"utf-8"> <title>演示例子</title> </head> <body> <style&g…

SQLAlchemy 2.0的简单使用教程

SQLAlchemy 2.0相比1.x进行了很大的更新&#xff0c;目前网上的教程不多&#xff0c;以下以链接mysql为例介绍一下基本的使用方法 环境及依赖 Python:3.8 mysql:8.3 Flask:3.0.3 SQLAlchemy:2.0.37 PyMySQL:1.1.1使用步骤 1、创建引擎&#xff0c;链接到mysql engine crea…

《LLM大语言模型+RAG实战+Langchain+ChatGLM-4+Transformer》

文章目录 Langchain的定义Langchain的组成三个核心组件实现整个核心组成部分 为什么要使用LangchainLangchain的底层原理Langchain实战操作LangSmithLangChain调用LLM安装openAI库-国内镜像源代码运行结果小结 使用Langchain的提示模板部署Langchain程序安装langserve代码请求格…

某网盘工具,限速下载上传!

聊一聊 某度盘对于个人和未开通会员的情况下&#xff0c;容量还是有点小。最近自己的盘满了&#xff0c;还有很多东西放不进去。转眼发现正在下载的寻雷&#xff0c;就点进去看看寻雷盘有多大&#xff0c;一看&#xff0c;还好&#xff0c;比某度盘容量大。 但一想&#xff0…

【后端开发】字节跳动青训营Cloudwego脚手架

Cloudwego脚手架使用 cwgo脚手架 cwgo脚手架 安装的命令&#xff1a; GOPROXYhttps://goproxy.cn/,direct go install github.com/cloudwego/cwgolatest依赖thriftgo的安装&#xff1a; go install github.com/cloudwego/thriftgolatest编辑echo.thrift文件用于生成项目&…

LabVIEW纤维集合体微电流测试仪

LabVIEW开发纤维集合体微电流测试仪。该设备精确测量纤维材料在特定电压下的电流变化&#xff0c;以分析纤维的结构、老化及回潮率等属性&#xff0c;对于纤维材料的科学研究及质量控制具有重要意义。 ​ 项目背景 在纤维材料的研究与应用中&#xff0c;电学性能是评估其性能…

Python 深拷贝与浅拷贝:数据复制的奥秘及回溯算法中的应用

引言 在 Python 编程领域&#xff0c;数据复制是极为常见的操作。而深拷贝和浅拷贝这两个概念&#xff0c;如同紧密关联却又各具特色的双子星&#xff0c;在数据处理过程中扮演着重要角色。深入理解它们&#xff0c;不仅有助于编写出高效、准确的代码&#xff0c;还能避免许多…