CAS:
CAS相对于计算器(count)++来说,count++在多线程的环境下是线程不安全的,那么就必须得加锁,而加了锁性能就会大打折扣,所以就有了CAS而CAS的操作是原子的,从而会保证线程的安全。本质操作是将线程A和内存里的数进行比较,如果相等则不会改变,如果不相等就会把线程B的值放在内存中,这里不考虑线程B的值为多少,只在乎内存的值是多少,而考虑到了CAS就会有一个ABA问题:
当我去银行给别人转账系统卡了我按了两下的取款操作,此时我有1000,然后我给别人转账500,然后我就剩了500,CAS的操作的话判断我之前的1000和之后只有500两个数不相等就不会出现问题,但是当我转账给别人500的时候,此时又有第三人给我转了500,那么我的金额就变回了原来的1000,此时的CAS操作不知道我的1000块是原来的1000还是别人修改的结果;
为了解决这个问题我们可以在弄一个内存记录线程的修改次数,当进行了一次修改那么就会+1,然后从这里开始比较的就是修改次数了,就不比较原来的值了
synchronized优化过程:
1.锁升级/锁膨胀:
synchronized在没有竞争的时候会变成一个偏向锁,这里的偏向锁没有加锁,只是一个状态
synchronized在有竞争的时候就会升级成为轻量级锁
synchronized在竞争激烈的时候就会变成重量级锁
这些都是JVM实现synchronized为了方便程序员的使用做出的优化
2.锁消除
当JVM发现程序的这个地方的代码没必要加锁,而此时如果你写上了synchronized,那么JVM就会自动帮你把锁消除掉。
当你的代码只有一个线程,或者有多个线程,但是多个线程不涉及修改同一个变量,但是你又加上了锁,那么JVM也会帮你自动去掉
针对与锁消除,只有在编译器/JVM认为有十足的把握才会消除,不然编译器/JVM也不会自动的消除
3.锁粗化
当synchronized对应包含的代码块内容比较多的时候粒度就比较粗,反之当synchronized包含的代码块少的时候,粒度就比较细。锁粗化的本质就是把细粒度的加锁转换成为粗粒度的加锁
好比如做工作一时加锁,做完了就解锁,然后在做工作二时加锁,做完了解锁,又开始做工作三时加锁,做完了就解锁,这些加锁虽然说是保证了线程的安全但是这里的顺序已经决定了不会影响线程,就会造成加锁解锁就会造成一些不必要的竞争,这样的一系列就称为锁的粒度比较细。
那么把细粒度加锁转换成粗粒度加锁就为:做工作一的时候加锁直到做完工作三时才解锁。
就好比给领导打电话汇报工作,锁的粒度比较细就是打一个电话汇报完第一个工作过后挂断,在打第二个电话汇报第二个工作持续这样。
而锁的粒度比较粗的情况下是:打电话给领导汇报工作一,工作二,工作三,结束电话。