1、乐观锁(版本号)
多个线程访问同一个共享数据时产生并发冲突的概率不大(多为单一节点信息,非全服务共享信息:用户个人信息)
解决方案:版本号(利用失败、重试方式处理),重试频繁也会对性能造成影响
2、悲观锁(挂起等待锁,以阻塞的方式)
多个线程访问同一个共享数据时产生并发冲突的概率较大(对CUP消耗较低,多为全服务共享信息:库存)
互斥加锁方式会涉及到用户态和内核态之间的切换:效率低、易阻塞
synchronized:Java当中不会对读和写进行区分,默认使用后线程都是互斥的
主要以悲观锁为主,初始使用乐观锁策略,但当发现锁竞争比较频繁的时候,就会自动切换成悲观锁策略
并不区分读写锁
synchronized自身已经设置好了自旋锁和挂起等待锁,会根据不同的情况自动选择最优的使用方案
读写锁:特殊的自旋锁,一个读写锁同时只能有一个写者或多个读者(与CPU数相关),但不能同时既有读者又有写者(多R或者1W,不能RW)。
自旋锁:是专为防止多处理器并发而引入的一种锁,它在内核中大量应用于中断处理等部分(对于单处理器来说,防止中断处理中的并发可简单采用关闭中断的方式,即在标志寄存器中关闭/打开中断标志位,不需要自旋锁),循环查看该自旋锁的保持者是否释放了锁,容易死锁,应用场景:CPU被占用次数少,时间短(并发度较低业务) ,因为休眠后唤醒操作比较浪费资源
线程任务对CPU比较敏感,且不希望吃太多CPU资源,那么此时就不太适合使用自旋锁
互斥锁:资源已经被占用,资源申请者只能进入睡眠状态
三. 重量级锁和轻量级锁
1. 原理
锁的核心特性 “原子性”,这样的机制追根溯源是 CPU 这样的硬件设备提供的
1.CPU 提供了 “原子操作指令”。
2. 操作系统基于 CPU 的原子指令,实现了 mutex 互斥锁.
3. JVM 基于操作系统提供的互斥锁。实现了 synchronized 和 ReentrantLock 等关键字和类。
注意:synchronized 并不仅仅是对 mutex 进行封装, 在 synchronized 内部还做了很多其他的工作
2. 理解
1.重量级锁依赖了OS提供的mutex,的开销一般很大,往往是通过内核来完成的
2.轻量级加锁一般不使用mutex,开销一般比较小,一般通过用户态就能直接完成
用户态:非特权状态,执行的代码被硬件限定,不能写:其他进程的存储空间,系统配置文件,重启系统等高危险操作