山西高端网站建设,只知道网站后台怎么做301,wordpress设置关键字,wordpress 上传权限悲观锁、乐观锁、自旋锁
#xff08;1#xff09;乐观锁
乐观锁是一种乐观的思想#xff0c;即认为读多写少#xff0c;遇到并发的可能性低#xff0c;每次拿数据时都认为别人不会修改#xff0c;所以不会上锁#xff0c;但是在更新的时候会判断一下在此期间别人有没有…悲观锁、乐观锁、自旋锁
1乐观锁
乐观锁是一种乐观的思想即认为读多写少遇到并发的可能性低每次拿数据时都认为别人不会修改所以不会上锁但是在更新的时候会判断一下在此期间别人有没有去更新这个数据可以使用 版本号机制(或时间戳) 和 CAS 算法实现。
Java 中的乐观锁基本都是通过 CAS 操作实现的CAS 是一种更新的原子操作比较当前值跟传入值是否一样一样则更新否则失败。
–缺点
ABA问题
CAS 会导致 “ABA 问题”。CAS 算法实现的一个重要前提是需要取出内存中某时刻的数据而在下一时刻比较并替换那么在这个时间差会导致数据的变化。
部分乐观锁的实现是通过版本号version的方式来解决 ABA 问题乐观锁每次在执行数据的修改操作时都会带上一个版本号一旦版本号和数据的版本号一致就可以执行修改操作并对版本号执行 1 操作否则就执行失败因为每次操作的版本号都会随着增加所有不会出现 ABA 的问题。
只能保证一个共享变量的原子操作
CAS 只对单个变量有效但涉及到多个共享变量时 CAS 无效
2悲观锁 悲观锁就是悲观的思想即认为写多遇到并发的可能性高每次拿数据时都会认为别人会修改数据所以在每次读数据的时候都会上锁这样当别人想读写这个数据时就会阻塞直到拿到锁。共享资源每次只给一个线程使用其它线程阻塞用完后再把资源转让给其它线程。传统的关系型数据库里边就用到了很多这种锁机制比如行锁表锁等读锁写锁等都是在做操作之前先上锁。
Java 中的悲观锁就是 SynchronizedAQS 框架下的锁则是先尝试 CAS 乐观锁去获取锁获取不到才会转换为悲观锁如 ReentrantLock
两种锁的使用场景 乐观锁适用于读多写少的情况即冲突真的很少发生的时候这样可以省去了锁的开销加大了系统的整个吐吞量。但如果是多写的情况下一般会经常产生冲突当获取锁失败时就要不断的进行自旋操作以尝试重新获取锁这样就会导致性能下降所以一般多写的场景下用悲观锁就比较合适。
3自旋锁 自旋锁原理非常简单如果持有锁的线程能在很短时间内释放锁资源那么那些等待竞争锁资源的线程就不需要做内核态与用户态之间的切换进入阻塞挂起状态它们只需要等一等自旋等待持有锁的线程释放锁后就可以立即获取锁这样就避免用户态与内核态的切换消耗。
线程自旋是需要消耗 CPU 的说白了就是让 CPU 在做无用功如果一直获取不到锁那线程也不能一直占用 CPU 自旋做无用功所以需要设定一个自旋等待的最大时间。
优缺点
自旋锁尽可能的减少线程的阻塞这对于锁的竞争不激烈且占用锁时间非常短的代码块来说性能大幅度的提升因为自旋的消耗会小于线程阻塞挂起再唤醒的操作消耗这些操作会导致线程发生两次上下文切换
但是如果锁的竞争激烈或持有锁的线程需要长时间占用锁执行同步块这时候就不适合使用自旋锁了因为自旋锁在获取锁前一直都是占用 CPU 做无用功占着 XX 不 XX同时有大量线程在竞争一个锁会导致获取锁的时间很长线程自旋的消耗大于线程阻塞的消耗其它需要 CPU 的线程又不能获取到 CPU造成 CPU 的浪费。所以这种情况下我们要关闭自旋锁。
深入理解CAS
public class casDemo {//CAS : compareAndSet 比较并交换public static void main(String[] args) {AtomicInteger atomicInteger new AtomicInteger(2020);//boolean compareAndSet(int expect, int update)//期望值、更新值//如果实际值 和 我的期望值相同那么就更新//如果实际值 和 我的期望值不同那么就不更新System.out.println(atomicInteger.compareAndSet(2020, 2021));System.out.println(atomicInteger.get());//因为期望值是2020 实际值却变成了2021 所以会修改失败//CAS 是CPU的并发原语atomicInteger.getAndIncrement(); //操作System.out.println(atomicInteger.compareAndSet(2020, 2021));System.out.println(atomicInteger.get());}
}Unsafe 类 总结
CAS比较当前工作内存中的值 和 主内存中的值如果这个值是期望的那么则执行操作如果不是就一直循环使用的是自旋锁。
缺点
循环会耗时一次性只能保证一个共享变量的原子性它会存在ABA问题
解决ABA问题对应的思想就是使用了乐观锁~-------带版本号的 原子操作