可重入锁
指同一个线程可以多次拿到同一把锁,而不会把自己锁死。这个最开始的时候,其实比较难理解。可以看下面这个不可重入锁的代码来理解。
- 模仿一个不可重入锁
1 | class Lock { |
- a()调用b(),他们都有获取锁。但是b()一直获取不到,就会导致死锁。
1 | Lock lock = new Lock(); |
感觉和spring事务那里有点像,后面弄到的时候在对比一下。
如果这个Lock是可重入锁,b()就可以正常的获取锁,不至于导致死锁。以下这些是我们常见的可重入锁:
synchronized也是一个可重入锁。ReentrantLock、ReentrantReadWriteLock是可重入锁。
公平锁和非公平锁
这个其实很好理解:
- 公平锁:多线程按照申请锁的顺序来获取锁。
- 非公平锁:多线程不按照申请锁的顺序来获取锁 。
我们常见的公平锁和非公平锁是:
synchronized只支持非公平锁。ReentrantLock、ReentrantReadWriteLock,默认是非公平锁,但支持公平锁。
独享锁与共享锁
独享锁与共享锁是一种广义上的说法,从实际用途上来看,也常被称为互斥锁与读写锁。
- 独享锁:锁一次只能被一个线程所持有。
- 共享锁:锁可被多个线程所持有。
我们常见的独享锁与共享锁是:
synchronized、ReentrantLock只支持独享锁。ReentrantReadWriteLock其写锁是独享锁,其读锁是共享锁。读锁是共享锁使得并发读是非常高效的,读写,写读 ,写写的过程是互斥的。
悲观锁与乐观锁
乐观锁与悲观锁不是指具体的什么类型的锁,而是处理并发同步的策略。
- 悲观锁:不加锁的并发操作一定会出问题。因此悲观锁适合写操作频繁的场景。
- 乐观锁:不加锁的并发操作也没什么问题。对于同一个数据的并发操作,是不会发生修改的。在更新数据的时候,会采用不断尝试更新的方式更新数据。因此乐观锁适合读多写少的场景。
常见的悲观锁与乐观锁:
synchronized和Lock。CAS以及各种原子类。
偏向锁、轻量级锁、重量级锁
所谓轻量级锁与重量级锁,指的是锁控制粒度的粗细。显然,控制粒度越细,阻塞开销越小,并发性也就越高。
- Java 1.6 以前,重量级锁一般指的是
synchronized,而轻量级锁指的是volatile。 - Java 1.6 以后,针对
synchronized做了大量优化,引入 4 种锁状态: 无锁状态、偏向锁、轻量级锁和重量级锁。锁可以单向的从偏向锁升级到轻量级锁,再从轻量级锁升级到重量级锁 。偏向锁 - 偏向锁是指一段同步代码一直被一个线程所访问,那么该线程会自动获取锁。降低获取锁的代价。
轻量级锁 - 是指当锁是偏向锁的时候,被另一个线程所访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋的形式尝试获取锁,不会阻塞,提高性能。
重量级锁 - 是指当锁为轻量级锁的时候,另一个线程虽然是自旋,但自旋不会一直持续下去,当自旋一定次数的时候,还没有获取到锁,就会进入阻塞,该锁膨胀为重量级锁。重量级锁会让其他申请的线程进入阻塞,性能降低。
分段锁
这个有个很经典的就是ConcurrentHashMap,把锁的对象分成多段,每段独立控制,使得锁粒度更细,减少阻塞开销,从而提高并发性。
参考
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 coder-xuyong!
评论





