并发编程 - 线程同步(五)之原子操作Interlocked详解二

360影视 2025-02-08 17:06 3

摘要:上一章我们学习了原子操作Interlocked类的几个常用方法,今天我们将继续学习该类的其他方法。

上一章我们学习了原子操作Interlocked类的几个常用方法,今天我们将继续学习该类的其他方法。

01、Exchange方法

该方法用于原子的将变量的值设置为新值,并返回变量的原始值。该方法共有14个重载方法,其中13个为常见的数据类型,有1个为泛型版本。

我们可以根据该方法可以原子更新一个变量并且可以同时获取该变量旧值这一特性,设计一个简单的锁机制,大致思路如下:

1.定义一个标志位,如果该标志位旧值为0表示当前线程获取锁,否则表示当前线程无法获取锁;

2.当线程获取锁后,可以进行业务处理,安全的处理非线程安全资源访问的代码;

3.当线程处理完业务后,释放锁,即更新标志位值为0,当前线程则退出锁,其他线程可以继续获取锁;

实现代码如下;

我们可以看看执行结果:

可以发现当一个线程获取锁后,其他线程则无法再获取该锁,只有当前线程处理完成业务退出改锁后,其他线程才可以继续获取该锁。

02、Exchange方法

该方法是Exchange方法的泛型版本,具体使用可以参考上一节。

03、CompareExchange方法

该方法用于原子的比较第一个变量和第三个变量是否相等,如果相等,则将第一个变量替换为第二个变量值,并返回第一个变量的原始值;该方法也有14个重载方法,其中13个为常见的数据类型,有1个为泛型版本。

可以理解为该方法比Exchange方法多了一个条件判断。因此该方法可以应用于更复杂的业务场景。

下面我们就使用该方法实现CAS(Compare and Swap)算法,并实现一个简单的版本控制功能。

所谓版本控制就是指使用一个版本号来表示对象的状态,每次更新该对象时,我们都希望确保只有当当前版本号与我们预期的版本号一致时才能执行更新操作。否则,说明在这期间有其他线程更新了该对象,我们需要放弃当前操作或者重试。

首先我们需要构建一个版本化数据类,该类中有两个字段用于分别用于存储数据和版本号;并提供两个方法,一个方法用于获取当前数据和版本号,一个方法用于通过版本号更新数据。具体实现代码如下:

完成版本化类设计后,就可以使用了,我们模拟两个线程,同时获取当前版本化数据和版本号,然后同时再更新数据,具体代码如下:

我们来看看执行结果:

通过结果可以发现只有1个线程更新成功了。

04、CompareExchange方法

该方法是CompareExchange方法的泛型版本,具体使用可以参考上一节。

05、And方法

该方法用于原子的对两个变量进行按位与操作,将第一个变量替换为操作结果,并返回第一个变量的原始值;该方法同样有4个重载方法,分别为long、ulong、int和uint四种数据类型;

主要还是用于多线程环境下,对共享变量进行安全的原子性按位与操作,避免并发修改时可能出现的数据不一致问题。

下面看一个简单的例子:

看看执行结果;

可以理解为就是两个数进行按位与运算,并且可以原子的更新原值,并返回原始值。

06、Or方法

该方法用于原子的对两个变量进行按位或操作,将第一个变量替换为操作结果,并返回第一个变量的原始值;该方法也有4个重载方法,分别为long、ulong、int和uint四种数据类型;

具体使用可以参考And方法。

07、MemoryBarrier方法

该方法用于强制执行内存屏障,作用范围当前线程,无返回值。后面有机会我们再详细讲解。

08、MemoryBarrierProcessWide方法

该方法用于提供进程范围的内存屏障,确保任何 CPU 的读取和写入无法跨屏障移动。后面有机会我们再详细讲解。


来源:IT规划师

相关推荐