C# Interlocked 原子操作

news2024/12/25 4:14:21

目录

注解

方法

适用于

案例

 1:Add 对两个整数进行求和并用和替换第一个整数,上述操作作为一个原子操作完成

2:Exchange  Exchange(UInt32, UInt32)  以原子操作的形式,将 32 位无符号整数设置为指定的值并返回原始值。


参考文档:Interlocked 类 (System.Threading) | Microsoft Learn

我对Interlocked原子操作的理解是:如同一桌人喝一碗汤,汤碗里面有一个公用的勺子,不能多个人同时使这把公用的勺子舀汤,  当有人想喝汤时(或者服务员想要加汤时),就得先拿到勺子,其他人就没法喝汤(或者添汤)。只有喝汤的人(添汤的人)用完勺子放回汤碗后,其他人才能继续使用勺子喝汤(添汤)。

注解

此类的方法可帮助防止在以下情况下发生的错误:在以下情况下发生:计划程序在以下情况下切换上下文:当线程正在更新可被其他线程访问的变量时,或当两个线程同时在不同的处理器上执行时。 此类的成员不会引发异常。

Increment和 Decrement 方法递增或递减变量,并在单个操作中存储生成的值。 在大多数计算机上,递增变量不是原子操作,需要执行以下步骤:

  1. 将实例变量中的值加载到寄存器中。

  2. 递增或减小值。

  3. 将值存储在实例变量中。

如果不使用 Increment 和,则在 Decrement 执行前两个步骤后,线程可以被抢占。 然后,另一个线程可以执行所有三个步骤。 当第一个线程继续执行时,它将覆盖实例变量中的值,并且由第二个线程执行的增量或减量的影响将丢失。

Add方法以原子方式将整数值添加到整数变量中,并返回变量的新值。

Exchange方法以原子方式交换指定变量的值。 CompareExchange方法组合了两个操作:比较两个值,并根据比较结果将第三个值存储在一个变量中。 比较和交换操作以原子操作的方式执行。

确保对共享变量的任何写入或读取访问都是原子的。 否则,数据可能已损坏,或者加载的值可能不正确。

方法

Add(Int32, Int32)

对两个 32 位整数进行求和并用和替换第一个整数,上述操作作为一个原子操作完成。

Add(Int64, Int64)

对两个 64 位整数进行求和并用和替换第一个整数,上述操作作为一个原子操作完成。

Add(UInt32, UInt32)

对两个 32 位无符号整数进行求和并用和替换第一个整数,上述操作作为一个原子操作完成。

Add(UInt64, UInt64)

对两个 64 位无符号整数进行求和并用和替换第一个整数,上述操作作为一个原子操作完成。

And(Int32, Int32)

对两个 32 位带符号整数进行按位“与”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。

And(Int64, Int64)

对两个 64 位带符号整数进行按位“与”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。

And(UInt32, UInt32)

对两个 32 位无符号整数进行按位“与”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。

And(UInt64, UInt64)

对两个 64 位无符号整数进行按位“与”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。

CompareExchange(Double, Double, Double)

比较两个双精度浮点数是否相等,如果相等,则替换第一个值。

CompareExchange(Int32, Int32, Int32)

比较两个 32 位有符号整数是否相等,如果相等,则替换第一个值。

CompareExchange(Int64, Int64, Int64)

比较两个 64 位有符号整数是否相等,如果相等,则替换第一个值。

CompareExchange(IntPtr, IntPtr, IntPtr)

比较两个平台特定的句柄或指针是否相等,如果相等,则替换第一个。

CompareExchange(Object, Object, Object)

比较两个对象是否引用相等,如果相等,则替换第一个对象。

CompareExchange(Single, Single, Single)

比较两个单精度浮点数是否相等,如果相等,则替换第一个值。

CompareExchange(UInt32, UInt32, UInt32)

比较两个 32 位无符号整数是否相等,如果相等,则替换第一个值。

CompareExchange(UInt64, UInt64, UInt64)

比较两个 64 位无符号整数是否相等,如果相等,则替换第一个值。

CompareExchange<T>(T, T, T)

比较指定的引用类型 T 的两个实例是否引用相等,如果相等,则替换第一个。

Decrement(Int32)

以原子操作的形式递减指定变量的值并存储结果。

Decrement(Int64)

以原子操作的形式递减指定变量的值并存储结果。

Decrement(UInt32)

以原子操作的形式递减指定变量的值并存储结果。

Decrement(UInt64)

以原子操作的形式递减指定变量的值并存储结果。

Exchange(Double, Double)

以原子操作的形式,将双精度浮点数设置为指定的值并返回原始值。

Exchange(Int32, Int32)

以原子操作的形式,将 32 位有符号整数设置为指定的值并返回原始值。

Exchange(Int64, Int64)

以原子操作的形式,将 64 位有符号整数设置为指定的值并返回原始值。

Exchange(IntPtr, IntPtr)

以原子操作的形式,将平台特定的句柄或指针设置为指定的值并返回原始值。

Exchange(Object, Object)

以原子操作的形式,将对象设置为指定的值并返回对原始对象的引用。

Exchange(Single, Single)

以原子操作的形式,将单精度浮点数设置为指定的值并返回原始值。

Exchange(UInt32, UInt32)

以原子操作的形式,将 32 位无符号整数设置为指定的值并返回原始值。

Exchange(UInt64, UInt64)

以原子操作的形式,将 64 位无符号整数设置为指定的值并返回原始值。

Exchange<T>(T, T)

以原子操作的形式,将指定类型 T 的变量设置为指定的值并返回原始值。

Increment(Int32)

以原子操作的形式递增指定变量的值并存储结果。

Increment(Int64)

以原子操作的形式递增指定变量的值并存储结果。

Increment(UInt32)

以原子操作的形式递增指定变量的值并存储结果。

Increment(UInt64)

以原子操作的形式递增指定变量的值并存储结果。

MemoryBarrier()

按如下方式同步内存存取:执行当前线程的处理器在对指令重新排序时,不能采用先执行 MemoryBarrier() 调用之后的内存存取,再执行 MemoryBarrier() 调用之前的内存存取的方式。

MemoryBarrierProcessWide()

提供覆盖整个过程的内存屏障,确保来自任何 CPU 的读写都不能越过该屏障。

Or(Int32, Int32)

对两个 32 位带符号整数进行按位“或”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。

Or(Int64, Int64)

对两个 64 位带符号整数进行按位“或”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。

Or(UInt32, UInt32)

对两个 32 位无符号整数进行按位“或”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。

Or(UInt64, UInt64)

对两个 64 位无符号整数进行按位“或”运算,并用结果替换第一个整数,上述操作作为一个原子操作完成。

Read(Int64)

返回一个以原子操作形式加载的 64 位值。

Read(UInt64)

返回一个以原子操作形式加载的 64 位无符号值。

适用于

产品Versions
.NET5.0
.NET Core1.0, 1.1, 2.0, 2.1, 2.2, 3.0, 3.1
.NET Framework1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8
.NET Standard1.0, 1.1, 1.2, 1.3, 1.4, 1.6, 2.0, 2.1
UWP10.0
Xamarin.Android7.1
Xamarin.iOS10.8
Xamarin.Mac3.0

案例

1:Add 

对两个整数进行求和并用和替换第一个整数,上述操作作为一个原子操作完成

2:Exchange  

以原子操作的形式,将设置为指定的值并返回原始值(或者对象)。

 public class InterlockedExchange
    {
        //0 资源未被使用, 1 资源被占用.
        private static int usingResource = 0;
        //每个线程执行次数
        private const int numThreadIterations = 5;
        //线程数
        private const int numThreads = 10;

        public static void Main1()
        {
            Thread myThread;
            Random rnd = new Random();

            for (int i = 0; i < numThreads; i++)
            {
                myThread = new Thread(new ThreadStart(MyThreadProc));
                myThread.Name = String.Format($"Thread{i + 1}");

                //在开始下一个线程之前随机等待一段时间。
                Thread.Sleep(rnd.Next(0, 1000));
                myThread.Start();
            }
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("主线程已执行完");
            Console.ResetColor();
        }

        private static void MyThreadProc()
        {
            while(true)
            {
                //如果任务 拿到资源执行
                if (UseResource()) break;

                //等待1秒再执行
                Thread.Sleep(1000);
            }
        }

        //A simple method that denies reentrancy.
        static bool UseResource()
        {
            //0 indicates that the method is not in use.
            if (0 == Interlocked.Exchange(ref usingResource, 1))
            {
                Console.WriteLine($"{Thread.CurrentThread.Name} 获得资源");

                //这里放 用于访问非线程安全的资源代码。

                //模仿 执行的任务,暂停500毫秒
                Thread.Sleep(500);

                Console.WriteLine($"{Thread.CurrentThread.Name} 释放资源");

                //Release the lock
                Interlocked.Exchange(ref usingResource, 0);
                return true;
            }
            else
            {
                Console.WriteLine($"   {Thread.CurrentThread.Name} 拿资源时,被拒绝");
                return false;
            }
        }
    }

执行结果

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

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

相关文章

【python - 函数】

一、测试 如果我们写出一下一些泛化的函数&#xff0c;①计算边长为r的正方形面积②半径为r的圆的面积③边长为r的六边形面积。 我们运行代码计算一下边长为10的六边形面积&#xff0c;可以看到它约等于260&#xff0c;但是我们计算一下边长为-10的六边形面积它也同样成功了&…

帝国CMS火车头采集发布模块详细使用方法

火车头采集文章数据发布到帝国CMS系统操作步骤如下&#xff1a; 1. 下载火车头采集帝国cms发布模块&#xff1a;帝国cms发布模块接口下载地址&#xff08;免登录&#xff09;-CSDN &#xff1b; 2. 帝国cms发布模块导入火车头采集软件&#xff1b; 3. 填写帝国cms数据库中相…

基于(C++)VTK9.3.0+Microsoft Visual Studio2017的DICOM影像VR体绘制完整实现代码

开发基于(C++)VTK9.3.0+Microsoft Visual Studio2017的DICOM影像VR体绘制程序的前提是: 1、已编译完成VTK9.3.0,可在VTK官网下载VTK9.3.0源码,官网下载地址:Download | VTK 选择所需的VTK版本进行下载 具体编译VTK的过程我就不详细介绍了,有需要可以提供支持。下面直接…

php yield使用

一&#xff0c;概念 yield简单的调用形式看起来像一个return申明&#xff0c;不同之处在于普通return会返回值并终止函数的执行&#xff0c;而yield会返回一个值给循环调用此生成器的代码并且只是暂停执行生成器函数。yield只有在调用的时候才会执行&#xff0c;并不产生多余的…

【2024Python教程】Python文件打包成exe,如果有图片怎么打包?有手就会的超简单教程

目录 pyinstaller模块打包exe&#xff08;无图片或其他文件打包版&#xff09; 第一步 安装pyinstaller模块&#xff1a; 第二步 找到需要打包的主程序文件夹 第三步 打包exe文件 第四步 确认exe文件是否可以打开 pyinstaller模块打包exe&#xff08;有图片打包版--方法一…

瑞幸携陈建斌迎“白月光”回归,品牌联名为何屡试不爽?

要说品牌联名看谁家&#xff0c;那真不得不提瑞幸。一招“酱香拿铁”直接“热翻”各大平台&#xff0c;不少网友感慨“人生第一杯茅台&#xff0c;居然是瑞幸给的”。而上个月瑞幸又上了一波“大招”&#xff0c;携手“大胖橘”陈建斌老师回归初代产品“橘金气泡美式”&#xf…

一文读懂数据中台

前言&#xff1a;数据中台的目标是让数据持续用起来&#xff0c;通过数据中台提供的工具、方法和运行机制&#xff0c;把数据变为一种服务能力&#xff0c;让数据更方便地被业务所使用。下图所示为数据中台总体架构图&#xff0c;数据中台是在底层存储计算平台与上层的数据应用…

Qt——窗口

目录 概述 菜单栏 创建菜单栏 创建子菜单 添加分割线 添加图标 工具栏 创建工具栏 设置初始位置和停靠位置 设置浮动属性 设置移动属性 状态栏 创建状态栏 显示实时消息 添加控件 浮动窗口 创建浮动窗口 对话框 创建对话框 对话框的分类 Qt 内置对话框 …

基于.Net 框架实现WebSocket 简单通信——服务端

新建项目 创建一个.Net 框架的控制台程序。 添加包 项目 → 管理 NuGet 程序包打开包管理窗口&#xff0c;添加SuperWebSocket 程序包。 实现 项目 → 添加类打开添加新项窗口&#xff0c;添加一个C#类。 启动监听 WebSocketServer socket new WebSocketServer();Conso…

浅谈DALL-E2

目录 1.概述 2.诞生背景 3.作用 4.版本历史 5.模型和技术 6.应用场景 6.1.十个应用场景 6.2.游戏开发 7.接口 8.未来展望 9.总结 1.概述 DALL-E2 是由 OpenAI 开发的一个图像生成模型&#xff0c;可以根据文本描述生成高质量的图像。DALL-E2 是 DALL-E 的升级版&am…

【小白学Python】自定义图片的生成(一)

目录标题 安装Pillowdemo代码初次代码计划 个人需要&#xff0c;基于文字生成图片。 除了AI外&#xff0c;对于简单的图片&#xff0c;Python在这方面也非常擅长。 我算是一个Python小白&#xff0c;除了业余时尝试过Python基本语法的练习&#xff0c;从未真正使用过Python。…

电流的本质是什么

话说很久以前&#xff0c;科学发现纯靠人眼识别。有一天&#xff0c;泰勒斯(古希腊哲学家&#xff0c;被称为科学的祖师爷)一时手痒&#xff0c;拿着琥珀与皮毛摩擦。 结果他发现那种半透明的小石头&#xff0c;居然产生了吸引小物体的魔力。 面对这个现象&#xff0c;老泰开始…

CRM客户关系管理:全方位客户关系管理解决方案

CRM客户关系管理系统&#xff0c;基于Spring Cloud Alibaba、Spring Boot、MybatisPlus、Redis和VUE3 ElementUI微服务架构&#xff0c;提供全面的客户关系管理功能。系统智能化地管理客户信息、线索跟踪、商机开发、合同管理、回款计划等&#xff0c;助力企业提升客户满意度&a…

资产管理系统是什么?主要有哪些功能?

资产管理系统主要对企业的固定资产、流动资产、长期投资等进行综合管理&#xff0c;通过先进的条形码技术对资产实物从购置、领用、清理、盘点、借用归还、维修到报废进行全方位准确监管。 一、资产管理系统主要包括哪些功能&#xff1f; 1、资产管理 &#xff08;1&#xf…

掌握Python的全方位教程,2024年最新版本,初学者必备指南

哈喽&#xff0c;大家好&#xff01;热烈欢迎你迈出成为python开发者的第一步。我想这一定非常激动人心&#xff0c;对吧&#xff1f;无论你是刚刚开始学习编程&#xff0c;还是曾经用过其他语言有一定的编程经验&#xff0c;本书中课程将帮助你加速实现你学习python的目标。作…

vue30:组件通信

父子关系 1&#xff1a;父组件通过props将数据传递给子组件 2&#xff1a;子组件利用$emi通知父组件修改更新

CISP究竟适合谁?这四类人没跑了

在信息技术飞速发展的现在&#xff0c;网络安全已经成为了一个不可忽视的话题。 CISP&#xff0c;即注册信息安全专业人员&#xff0c;是网络安全领域内一项备受认可的专业认证。 但CISP究竟适合谁考呢&#xff1f;这不仅是一个技术问题&#xff0c;更是一个职业规划的问题。…

用友U8 许可更新

当登录U8客户端提示下面的界面时&#xff0c;需要联网更新许可 登录服务器&#xff0c;打开Win下面的许可管理 导入许可——在线同步许可 更新完成即可

重温react-01

创建react项目 // 第一步 npm install create-react-app -g // 第二步 create-react-app my-app目录介绍 my-app/README.md# 项目第三方依赖包node_modules/package.json# 一般用来存放静态依赖public/index.htmlfavicon.ico# 存放项目源代码&#xff0c;注意只有放在scr目录…

java:使用JSqlParser给sql语句增加tenant_id和deleted条件

# 示例代码 【pom.xml】 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-core</artifactId><version>3.4.3.1</version> </dependency>【MyJSqlParserTest.java】 package com.chz.myJSqlParser;pu…