首页 > 其他分享 >Delphi原子操作函数介绍

Delphi原子操作函数介绍

时间:2023-04-30 10:35:34浏览次数:32  
标签:function 函数 Delphi overload 原子 static var class Target

一、Delphi的原子操作函数

在System.SyncObjs单元中,有一个TInterlocked的密封类,其十多个类函数(class function)其实都是调用的System单元的原子操作函数,只是封装得更容易理解。

使用方法:如对一个数值加一,则直接b:= TInterlocked.Increment(a);或TInterlocked.Increment(a);,不用创建TInterlocked类(类函数相当于就是单独的函数,可以直接调用,不用实例化对象)

1、对一个数值变量加一和减一操作

//实际是调用System单元的AtomicIncrement函数

//对Target加一,并返回加一后的结果

class function Increment(var Target: Integer): Integer; overload; static; inline;

class function Increment(var Target: Int64): Int64; overload; static; inline;

//对Target减一,并返回减一后的结果

class function Decrement(var Target: Integer): Integer; overload; static; inline;

class function Decrement(var Target: Int64): Int64; overload; static; inline;

实例一:

var

a,b:integer;

begin

a:=1;

b:= TInterlocked.Increment(a);

//则b=2(等于a加一后的结果),同时a=2(a=1+1),而这时的a加一是原子操作,不会受多线程影响,能够保证数据一致性。

end;

2、对一个数值、指针、对象地址、泛型类的地址进行替换操作

//将Target替换为Value,并返回原来的Target值

//实际是调用System单元的AtomicExchange函数

class function Exchange(var Target: Pointer; Value: Pointer): Pointer; overload; static; inline;
class function Exchange(var Target: Integer; Value: Integer): Integer; overload; static; inline;
class function Exchange(var Target: Int64; Value: Int64): Int64; overload; static; inline;
class function Exchange(var Target: TObject; Value: TObject): TObject; overload; static; inline;
class function Exchange(var Target: Double; Value: Double): Double; overload; static; inline;
class function Exchange(var Target: Single; Value: Single): Single; overload; static; inline;

class function Exchange<T: class>(var Target: T; Value: T): T; overload; static; inline;

实例二:

var

a,b,c:integer;

begin

a:=1;

b:=2;

c:= TInterlocked.Exchange(a,b);

//则c=1(等于a之前的值),同时a=2(a被替换成b的值),而这时的a是原子操作,不会受多线程影响,能够保证数据一致性。

end;

3、比较两个值,相同时,用一个值替换掉目标值

//比较Target与Comparand两个值,当两个值相等,则将Target的值替换为Value的值,这个过程非常重要,是实现原子锁的核心

//实际是调用System单元的AtomicCmpExchange函数

class function CompareExchange(var Target: Pointer; Value: Pointer; Comparand: Pointer): Pointer; overload; static; inline;
class function CompareExchange(var Target: Integer; Value: Integer; Comparand: Integer): Integer; overload; static; inline;
class function CompareExchange(var Target: Integer; Value: Integer; Comparand: Integer; out Succeeded: Boolean): Integer; overload; static;
class function CompareExchange(var Target: Int64; Value: Int64; Comparand: Int64): Int64; overload; static; inline;
class function CompareExchange(var Target: TObject; Value: TObject; Comparand: TObject): TObject; overload; static; inline;
class function CompareExchange(var Target: Double; Value: Double; Comparand: Double): Double; overload; static; inline;
class function CompareExchange(var Target: Single; Value: Single; Comparand: Single): Single; overload; static; inline;

class function CompareExchange<T: class>(var Target: T; Value: T; Comparand: T): T; overload; static; inline;

这里要分成比较值相等和不相等两种情况

实例三:

var

a,b,c,d,e:integer;

begin

a:=1;

b:=2;

c:=3;

e:=1;

//比较a与c的值是否相等,相等则用b的值替换掉a的值,不相等则不替换

//由于a等于e(都等于1),则a的值被替换成b的值,即a=2,同时d等于a原来的值,即d=1

d:=TInterlocked.CompareExchange(a,b,e);

//由于a不等于c的值,所以a不会被替换,则d=1(等于a的值)

d:= TInterlocked.CompareExchange(a,b,c);

//注意了,不管a是否等于c和e的值,返回的一定是a原来的值,这个特性非常容易让我们判断a值到底是多少。

end;


4、用原子操作性读取一个数值

//如果在32位多线程中直接读取一个64位变量,寄存器是分为高字节和低字节两个部分,会读到脏数据,用原子操作读取则不会

class function Read(var Target: Int64): Int64; static; inline;

实际是调用System单元的AtomicExchange函数,如:b:=AtomicExchange(a,0,0);,始终会取到a原来的值,所以并不限于int64类型。

标签:function,函数,Delphi,overload,原子,static,var,class,Target
From: https://www.cnblogs.com/del88/p/17364970.html

相关文章

  • C语言函数大全-- s 开头的函数(3)
    C语言函数大全本篇介绍C语言函数大全--s开头的函数(3)1.sleep1.1函数说明函数声明函数功能unsignedintsleep(unsignedintseconds);它是C语言标准库中的函数,用于使当前进程挂起一定的时间。在挂起期间,操作系统会将该进程从调度队列中移除,直到指定的时间过去为......
  • linux c/c++程序集成python库,实现调用python函数
    为了提高开发效率,扩展开发程序的功能,我们经常会在我们的linuxc/c++进程里调用外部脚本,例如lua、python,下面,介绍下如何在自己的linuxc/c++代码里调用python脚本里的函数和类,并且将python库集成到我们自己的进程目录里,这样就不依赖系统环境是否存在python及其版本要求。 ......
  • 06 - react的类组件中的状态state render函数 this指向问题 事件绑定
    //注册事件importReactDomfrom"react-dom"import{Component}from"react"//类组件中的状态通过this.state.xxx来获取状态classHelloextendsComponent{//事件对象eventhandleClick(e){console.log(this)//udnefiend使用箭头函数解决this......
  • matlab出现函数或变量'fun1'无法识别出错fmincon(line 562)
    函数或变量'fun1'无法识别出错fmincon(line562)原因有两个1.函数名要与函数文件名相同如这里我的函数名是fun1,那么这个文件也要命名为fun12.路径出现了问题通常情况下matlab运行的时候是在C盘对应的bin目录下,但是我保存的这些代码文件并不是再C盘而是在D盘所以我们要进行手......
  • react的类组件和函数组件 -- 状态 state
    //函数组件是无状态的既没有数据的类似vue组件中的data数据//类组件是有状态的组件是有数据的是双向绑定的数据是数据驱动视图的负责UI的视图更新(单个组件的私有数据组件之间的数据是独立的)importReactDomfrom"react-dom"import{Component}from"react......
  • 定义函数时不要使用可变类型作为参数的默认值
    《流畅的Python》第8章8.4.1小节 可变默认值导致的这个问题说明了为什么通常使用None作为接收可变值的参数的默认值。类名.__init__.__defaults__:查看类中形式参数的默认值函数名.__defaults__属性:查看形式参数的默认值#形式参数L是可变类型时隐藏的问题defadd_end(L=[......
  • Cygwin、MSYS2 Bash封装函数restart,重启Windows程序进程向导,输入序号一键重启对应进程
    概述作用:终端输入restart,根据菜单提示输入序号重启特定的软件或进程,定义的重启函数太多不便于记忆的情况,特别是手机远程终端(如:JuiceSSH)连接的情况下,减少手动输入和误操作,其中判定浏览器进程使用了另一篇文章中预定的函数wmicps,ps2为指向wmicps的alias(详见:https://www.cnblog......
  • 生成函数GeneratingFunction
    生成函数GeneratingFunction极限\(\forall\rightarrow\)对于\(\exists\rightarrow\)存在极限:\(\forall\epsilon,\existsN,N>n,|a_n-A|<\epsilon\)就是说,对于所有(任意小的非负整数)\(\epsilon\)存在\(N\),使得\(a_n\)与A的差值小于\(\epsilon\)我们就把\(A\)叫做此序列......
  • python高阶用法汇总——(1)高阶函数
    lambda1defsum(a,b):2returna+b3print(sum(1,5))45lab=lambdaa,b:a+b6print(lab(1,3))1-3行正常用法,5-6lambda用法。lambda:冒号之前的全是参数,即函数括号里面的 sum(a,b)冒号之后的是表达式,即return的结果。lambda只能写在一行。一般情况下,我们不使用......
  • 构造函数和析构函数
    1.概念引入在说明构造函数和析构函数的概念之前,首先看一个例子下面这段代码是栈经典的应用场景括号匹配如图,栈必须先初始化,然后在每一个returnfalse之前都需要销毁栈,不然就会内存泄漏这样很繁琐,而且有些时候很容易忘记写,所以在C++中添加默认的成员函数,构造函数和......