悲观锁和乐观锁
根据线程是否要锁住同步资源可以将锁分为悲观锁和乐观锁。
悲观锁
悲观锁认为自己在使用数据的时候一定有线程来修改数据,所以在获取到数据的时候会先加锁,确保数据不会被别的线程修改。
实现有:关键字 synchronized 、接口 Lock的实现类。
适用于写多读少的场景。
乐观锁
乐观锁认为自己在使用数据的时候不会被别的线程修改,所有不会添加锁,只是在更新数据的时候才去判断之前有没有别的线程更新了这个数据。
实现有:使用CAS算法,例如:atomic包的原子类。
适用于读多写少的场景。
CAS算法
CompareAndSwap:比较与交换。
处理逻辑:当多条线程同时来修改堆上线程共享的值时,会先将堆上的值拷贝到自己的工作栈中。
当线程修改了自己工作栈中值后将值更新到堆上时,先进行判断,预期值和当前堆上的值是否一致,如果一致,则更新。当更新失败时要不自旋、要不报错,如果自旋一般设置一个默认的自旋次数。
此时可以参考Java内存模型(JMM,区别于JVM内存模型) 加深影响。
CAS算法中的ABA问题:
主存中的原始值:0
线程1:通过CAS将其修改为1
线程2:通过CAS将其修改为0
线程3:通过CAS来判断时以为没有修改
解决:通过增加版本号来解决。JAVA中已经解决了这个问题。