【前言】在日常开发工作中,我们经常要对变量进行操作,例如对一个int变量递增++ 。在单线程环境下是没有问题的,但是如果一个变量被多个线程操作,那就有可能出现结果和预期不一致的问题 。
例如:
static void Main(string[] args){var j = 0;for (int i = 0; i < 100; i++){j++;}Console.WriteLine(j);//100}
在单线程情况下执行,结果一定为100,那么在多线程情况下呢?
static void Main(string[] args){var j = 0;var t1 = Task.Run(() =>{for (int i = 0; i < 50000; i++){j++;}});var t2 = Task.Run(() =>{for (int i = 0; i < 50000; i++){j++;}});Task.WaitAll(t1, t2);Console.WriteLine(j);//82869 这个结果是随机的,和每个线程执行情况有关}
我们可以看到,多线程情况下并不能保证执行正确,我们也将这种情况称为 “非线程安全”
这种情况下我们可以通过加锁来达到线程安全的目的
static void Main(string[] args){var locker = new object();var j = 0;var t1 = Task.Run(() =>{for (int i = 0; i < 50000; i++){lock (locker){j++;}}});var t2 = Task.Run(() =>{for (int i = 0; i < 50000; i++){lock (locker){j++;}}});Task.WaitAll(t1, t2);Console.WriteLine(j);//100000 这里是一定的}
加锁的确能解决上述问题,那么有没有一种更加轻量级,更加简洁的写法呢?
那么,今天我们就来认识一下 Interlocked 类
【Interlocked 类下的方法】Increment(ref int location)Increment 方法可以轻松实现线程安全的变量自增
/// <summary>/// thread safe increament/// </summary>public static void Increament(){var j = 0;Task.WaitAll(Enumerable.Range(0, 50).Select(t =>Task.Run(() =>{for (int i = 0; i < 2000; i++){Interlocked.Increment(ref j);}})).ToArray());Console.WriteLine($"multi thread increament result={j}");//result=100000}
看到这里,我们一定好奇这个方法底层是怎么实现的?
我们通过ILSpy反编译查看源码:
首先看到 Increment
方法其实是通过调用 Add
方法来实现自增的
文章插图
再往下看,
Add
方法是通过 ExchangeAdd
方法来实现原子性的自增,因为该方法返回值是增加前的原值,因此返回时增加了本次新增的,结果便是相加的结果,当然 location1
变量已经递增成功了,这里只是为了友好地返回增加后的结果 。文章插图
我们再往下看
文章插图
这个方法用
[MethodImpl(MethodImplOptions.InternalCall)]
修饰,表明这里调用的是 CLR 内部代码,我们只能通过查看源码来继续学习 。我们打开 dotnetcore 源码:https://github.com/dotnet/corefx
找到
Interlocked
中的 ExchangeAdd
方法文章插图
可以看到,该方法用循环不断自旋赋值并检查是否赋值成功(CompareExchange返回的是修改前的值,如果返回结果和修改前结果是一致,则说明修改成功)
我们继续看内部实现
文章插图
文章插图
内部调用
InterlockedCompareExchange
函数,再往下就是直接调用的C++源码了文章插图
文章插图
在这里将变量添加
经验总结扩展阅读
- 常用CSS样式属性
- 2022年小雪节气能办婚宴吗
- 2022年农历腊月十一结婚日子如何
- 2023年农历八月初三搬家吉日 2023年9月17日适合搬家吗
- 迷你世界8月28日有哪些礼包
- 2022年12月24日平安夜适合乔迁吗
- 下个月痴迷旧爱 3大星座痴爱缠绵旧爱上门
- iqoo neo5优缺点_iqooneo5的缺点
- 2023年农历八月初三宜粉刷墙壁吗 2023年9月17日粉刷墙壁好吗
- 2023年专科最吃香的专业 什么专业未来有发展