00:00
各位同学大家好,接下来我为大家介绍第八章CAS。好,看到了三个英文字母,马上脑子里面就应该想出我们学习技术的方法论,它是什么,能干什么。怎么会出现的?解决了哪些痛点?没有它之前我们是怎么做的?有了它之后我们有哪些便捷方便的方法和API的调用可以更我们帮助我们更好的解决问题?好,那么首先我们来看一下,在学习这一个知识点的时候,第八章和第九章原子操作类这块是有前后关联和照应的,那么所以说我们呢?CS的时候会牵扯一些原子操作类的内容,那讲到原子操作类的内容的时候,又会反过来复习cns,两者前后关联,那么在这儿给大家做一下简单的说明,好,那么同学们一说起CS来吧。我们呢,先来了解一个前期知识,叫原子类,何为原子类呢?我们也见过,也就是我们GC并发包下面的凹通米克,这个包下面的所有相关的类和API的调用,来,大家请看就它,那么在这个下面有这么多类,这些类几乎都是CS思想的落地实现,那么为了保证后续的教学效果,我们先混个眼熟,下一章再来详细的说原子类,但是相信大家也不陌生。
01:26
最经典的我们是不是也多次用过我们的原子整形啊?好,那接下来我们来看一下假设啊,我们要针对于I加加这样的操作,没有CS之前,我们先不要管CS是什么啊,待会儿我们聊。来吧。多线程环境下面,如果我们不使用原子类。要保证线程安全的A加加操作,假设这个I是一个in特性的基本数据类型,那么我们会怎么干?来,同学们请看脑图,这个代码呢很简单,我们呢直接在脑图里面给大家进行说明。首先。
02:01
Number我们要做加加,通过前面的讲解都晓得,在高并发的环境下面,如果不加锁,这个写操作是一定会出问题的,所以我们为了保证原子性和数据的一致性,一般对于写操作我们必须要加入写锁的保护,那么对于读,为了保证它的并发性,一般我们不加锁,对吧?如果说是读多写少的情况下,那么但是这个变量我明白了,Tell,那么大家去读的时候保证可以读到最新版本,这个是可以帮你解决爱家家的线程安全问题的,用size。可不可以,完全可以,但是它有个问题,Size是一个比较重的技术点,你加入以后确确实实。能解决现场安全问题,但是系统运用的时候比较重,那么接下来我们会发现,如果我们使用CS,也即我们使用什么CS的这种思想的一种最好的落地工具类奥米包,那么这个时候大家请看。
03:02
多线程环境下面,上面是不使用,下面是使用原子类的话,我们就可以替代掉我们的S了。来打。这是上一版SNCH,下面我们就看,我们呢也没有定义一个的number型的变量,我们直接干了一个in原子整形类。这默认就是零开始,大家请看get和set读写,那么这个时候我们来看看如果我们要做I加加类似这样的操作。Set是写入直接调用原子类get and,那么这个呢,API我相信一读万文之意吧,先get,然后得到这个值,返回以后再对它进行increase加加,哎,那么所以说同学们这个就是我们的I加加,那么是原子类的下面。这个完了以后,上面这个get,那么就是得到这个原子呢,目前被加为多少是个get,非常简单的API调用,两者有什么区别,大家请看。
04:06
这哥们是不是根本没有加snchize这样的重量极所?所以说从性能上奥MIC inter它会比加snchize要轻便,要简洁,也即既能保证原子安全性,又不用SNCH加锁,这样是不是要两全其美啊?好,那么首先所以说是CS这种思想就有点类似于我们的乐观所,那么为什么会跟乐观所扯一块呢?那么下面我们来看一下CS啊是什么,再说一下它落地的思想和支撑的理念。来。同学们首先。什么叫cns啊?Compare and swap,还有你会看到它有些地方呢,写成set,好,那么这待会我们源码说话底子其实就是它哈,中文翻译成比较并什么交换是实现并发算法时常用到的一种技术,这个工作中天天用非常重要,那么它包含三个操作数。
05:06
内存位置。预期的原值以及更新值。好,我们先过一遍理论,待会儿详细说明。我们在执行CS操作的时候,将内存位置的值与预预期的原值来进行比较。如果这两个比较是相匹配,那么处理器会自动将该位置的值更新为最新的值。如果不匹配,处理器。不会做任何操作,多个线程同时执行CS操作,怎么着,只有一个会成功,也就多线程来抢这个资源,也跟锁一样,只会有一个抢所成功,好那么它的原理以及这的什么所谓的什么内存位置啊,预期啊,更新值什么,比较匹配还是不匹配什么意思呢?再给大家画个图来。三个操作数。所以CS内存位置。
06:03
那那那个位置的某个,呃,我们这有个叫偏移量啊,某个对象,它在内存里面的这个值叫内存值是V,旧的预期值是A,要修改的更新值是B,那么这我们来说一下。当且仅单旧的预期值A和内存的值相。同的时候,将内存值V修改为B,否则什么都不做或者是重试了,那么当它重来,重试的这种行为就称为自学这种思想好,这个就是我们CS的一个初级入门的理念来。案例说话,那么下面我们拿一个案例来给大家进一步的说一下什么是CS操作,以及什么叫自学来同学们,这个是我们的架构图,那么现在有这么一个案例,这块呢,是一个主物理内存的一个共享空间,它里面有个值,初始值啊。五那么现在呢?
07:02
多个线程都可以访问它。但是听好此时我们。不用。OK,我们不许用SYNCH的,那么也就是说前面讲过这个比较重,那么我们现在呢。进化到了一个CS的思想,它的用法是这样的,那么现在呢?这个就是我们的A线程,这个呢是我们的B线程,这个呢是我们的C线程,那么现在呢,不加锁。你不加锁,你自然而然多线程去写,就会容易导致数据错乱,那么现在我们要求不加S,还要保证数据不乱,数据一致性又能获得保证,并且性能还要好,就是既要又要,那么CS思想就干这货那么来。走起,那么首先多线程来操作这个共享内存,只能是先把它读到自己的本地内存,对吧?这个值呢,假设现在在A线程,这是五,那么现在也就是我们所谓的是吗?
08:06
这个我就是旧的预期值,我来碰的时候,A来碰的时候就是我好,那么现在A干活了,干完活以后,我呢自己呢,已经把这个值呢,在我这儿改为了六。I加加满五加一,下面我我的意思就是我准备把六写回进共享着主物理内存,那此时呢,我呢,用CS这个思想,我很乐观的认为我A在。工作的时候。B跟C以及其他线程根本没有去动主物理内存的数值,换句话说就是V中的值是否和A值相等,我们来判断,我很乐观的认为我拿出去的时候是五,我准备写回来的时候还是五,那么也就是说相等,那么将会用这个六去更新内存空间的值,我很乐观的认为别人没有改过,OK,拿的时候是我,回来的时候还是我,那么我就把六写回去,那么此时这个呢?
09:09
就是我们的什么CAS这样的一个比较和操作好相同了相等。我们呢,更新可是。没有那么多好事儿,别的县城可能也来干了。假设啊,现在。抱歉,A要准备把六写回去的时候,B跟C其实呢都做了一次,他们呢已经把这个值啊加了两次以后,其实是七了,那么现在我们呢A呢就回来了。我拿的时候是五,我的期望值也希望是五,那么只要是拿的时候是五,回来的时候还是我,我就认为很乐观的,认为别人没动过,但是大家都清楚啊,盲目乐观是不是一定会出错啊,那非常抱歉,这次被打脸了。A准备把六写回来的时候,发现预期值不再是五了。而且真实值已经比我的预期值高了两个档,相当于说版本已经比我手头上的更新了,那么非常抱歉,A本次的可能就作废了,那么他只好什么再去抢夺。
10:09
这个我不甘心啊,要么我直接放弃出局,要么我再来一次,因为我要把我自己手头上这次爱加加这次操作给做完,所以说此时A呢重振旗鼓。不服输,我再来一次啊,那么这个就是我们这儿所说的。要么你A什么都不做,放弃出局,要么你重来一次啊,这种重来重试的行为就叫自选,那么来此时这个A再来一次,哟,太好了,我这个时候抢到锁了,那么我读的值是七。那么好,做一次I加加操作将会变成八老规矩,再来一次CS啊,我读的时候是七,准备写回去的时候来判断一下它呢。旧的预期值还是不是七,如果是七就把我的八写回来,如果抱歉已经不再是七了,那么我本次又失败一次,我只好要么放弃,要么再来一次咨询,再去抢锁,然后再如法炮制上面的流程,那么这个就是我们的什么CAS的思想比较比较坏。
我来说两句