锁的分类
可重入锁&不可重入锁
- 可重入:当一个线程获取某个锁后,再次获取这个锁的时候是可以直接拿到的。
- 不可重入:当一个线程获取某个锁之后,再次获取这个锁的时候拿不到,必须等自己先释放锁再获取。
- synchronized、ReentrantLock、ReentrantLockReadWriteLock都是可重入锁。
乐观锁&悲观锁
- 乐观锁:当一个获取不到锁时,可以再次让CPU调度,重新尝试获取锁
- 悲观锁:当一个线程获取不到资源时,线程被挂起(BLOCKED,WAITING状态)。注意:线程挂起涉及到内核态和用户态的切换,比较消耗资源
- 用户态:JVM可以自行执行的指令,不需要操作系统执行。
- 内核态:JVM不可以自行执行,需要操作系统执行。
- synchronized、ReentrantLock、ReentrantLockReadWriteLock都是悲观锁,而Java中的CAS操作是一种乐观锁的实现。
共享锁&互斥锁
- 互斥锁:同一时间点只能有一个线程持有互斥锁。
- 共享锁:同一时间可以允许多个线程同时持有共享锁。
- synchronized和ReentrantLock是互斥锁。
- ReentrantLockReadWriteLock在读锁时候是共享锁,写锁时候是互斥锁。
公平锁&非公平锁
假设A线程持有锁,B线程正在等待锁,这个时候C线程来了
- 公平锁:C线程必须再B线程之后排队,必须等B线程获取锁或取消排队后C线程才能尝试获取锁。
- 非公平锁:C线程无视B的存在,先尝试获取锁,如果拿到锁就可以去执行业务逻辑,如果没拿到还是要去B线程后排队,等待B线程拿到锁,才能尝试获取锁
- synchronized是非公平锁
- ReentrantLock、ReentrantLockReadWriteLock可以是公平锁,也可以是非公平锁。