一、Java锁
1、乐观锁
乐观锁是一种乐观思想,认为读多写少,遇到并发写的可能性低,每次拿数据的时候都认为别人会修改,所以不会上锁。
但是在更新的时候会判断一下在期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加锁操作。比较跟上一次的版本号,如果一样则更新,如果失败则要重复读-比较-写的操作。
Java的乐观锁基本都是通过CAS操作实现的。CAS是一种更新的原子操作,比较当前值是否一样,一样则更新,否则失败。
2、悲观锁
悲观锁就是悲观思想,认为写多,遇到并发写的可能性高,每次去拿数据的时候都认为别人会修改,所以每次在读写数据的时候都会上锁,这样别人想读写这个数据就会block直到拿到锁。java中的悲观锁就是
synchronized,AQS框架下的锁则是先尝试CAS乐观锁去获取锁,获取不到才会转换为悲观锁,比如RetreenLock。
3、自旋锁
自选锁原理非常简单,如果持有锁的线程能在很短时间内释放锁资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进行阻塞挂起状态,他们只需要等一等(自旋),等持有锁的线程释放锁后就可以立即获取到锁,这样就避免了用户线程和内核的切换消耗。
线程自旋需要消耗CPU,说白了就是让CPU再做无用功,如果一直获取不到锁,那么线程也不能一直占用CPU自旋做无用功,所以需要设定一个自旋等待的最大时间。
如果持有锁的线程执行的时间超过自旋等待的最大时间仍没有释放锁,就会导致其他的线程在最大等待时间内还是获取不到锁,这时其他线程就会停止自旋进入阻塞状态。
- 本文作者: Victor Dan
- 本文链接: https://anonymousdq.github.io/victor.github.io/2019/06/11/Java锁/
- 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!