CAS乐观锁

synchronized:

1. syncronized运行的时候是jvm自动生成的代码,并不是我们自动定义的,.

2. 当我们用synchronized修饰类或方法时,jvm运行到此处在执行阶段会生成一个字节码文件叫做monitor监控变量,

3. 有两个变量一个叫做monitorEnter进行监控,一个叫做monitorExit用来结束当前锁,

4.执行到锁同步代码块或者同步方法锁的时候,线程进入到锁之后,monitorEnter进入到监控的范围之内,当拿到锁,monitorEnter值就从0变成1,

5.当其他的线程进行访问时,首先看monitorEnter值是几,因为synchronized是重量级锁,如果是1就阻塞,而且再获取的时候的顺序不是先后顺序,所以还是非公平锁,也就是说它即是非公平锁又是重量锁,其次他还是悲观锁

6.线程执行到结尾之后执行monitorExit,这是其他线程可进行获取锁

Lock:

既可以做公平锁又可以做非公平锁,由lock和unlock组成,等锁住以后当前值设为true,其他线程进行访问的时候就无法进行访问,执行lock锁的时候不会给我们生成什么东西,全部都是自己写的逻辑代码

锁开销的概念:

创建锁,获得锁,释放锁,都需要耗费内存空间以及cpu的时间,无锁,偏向锁,轻量级锁的方式,进行节省锁开销

悲观锁

当一个线程使用数据时,悲观锁总是认为其它线程也会过来修改这个数据。为了保证数据安全,其采用的是一种先加锁再访问的策略,其它线程要想也访问该数据则被阻塞等待、所以悲观锁也是重量锁,直到其获取到锁才可以访问。典型的,Java中的synchronized锁就是悲观锁

乐观锁

而对于乐观锁而言,其与悲观锁的思想则恰恰相反,其认为在使用数据的过程中其它线程不会修改这个数据,故不加锁直接访问。而当该线程需要提交更新、修改时,才会判断该数据在此期间有没有被其它线程更新、修改。如果其它线程确实没有修改,则该线程直接写入完成更新;反之如果该数据已经被其它线程更新、修改,则该线程将放弃本次数据的更新提交操作以避免出现冲突,并通过报错、重试等方式进行下一步处理。而我们这里即将介绍的CAS算法就是乐观锁的一种典型实现

CAS 比较与交换算法

在CAS(比较与交换)算法中涉及3个操作数:变量当前内存值V、变量的预期值E、新值U。只有该变量当前的内存值V与预期值E相同时,才会将新值U写入内存完成变量修改,否则什么都不做。CAS通过该变量的地址即可获取该变量当前的内存值V。当本轮CAS操作失败后,会重新读取该变量内存中最新的值并重新计算新值,直到其CAS操作修改变量成功为止

do{
    1. 读取变量值,记为E。用于写入修改时,判断该变量是否被修改
    2. 使用读到的变量值E,计算该变量的新值,记为U
} while( !CAS(变量内存地址,E,U) )

ABA问题

我们知道在CAS操作中,判断变量是否被其他线程修改,是通过比较当前内存值V和预期值E来完成的。现在考虑这样一个场景,线程1读到某变量的值为A,在其计算新值的过程中,另外一个线程2已经将该变量的值从A先修改为B、然后又将其从B修改回A。此时,当线程1通过CAS操作进行新值写入虽然可以成功,而实际上线程1执行CAS操作时 预期值的A 和 读取该变量当前值的A 已经不是"同一个"了,因为后者是线程2修改的

之所以会产生ABA问题是因为变量的值存在环形转换,而如果该变量只能朝着一个方向变化(例如一个自增的主键ID变量),就不会出现该问题。而对于ABA问题则可以通过给变量附加时间戳、版本号等信息来解决

你可能感兴趣的:(java,p2p,linq,java)