公平锁,非公平锁,可重入锁,递归锁,自旋锁
(共享锁)读锁,(独占锁)写锁,互斥锁
独占式:只有一个线程能执行,具体的 Java 实现有 ReentrantLock。
共享式:多个线程可同时执行,具体的 Java 实现有 Semaphore和CountDownLatch。
手写一个自旋锁
公平锁和非公平锁
公平锁:多个线程按照申请锁的顺序来获取锁
非公平锁:不按照顺序,有点是吞吐量比公平锁大。
synchronized也是非公平锁
ReentrantLock默认非公平锁
/**
* Creates an instance of {@code ReentrantLock}.
* This is equivalent to using {@code ReentrantLock(false)}.
*/
public ReentrantLock() {
sync = new NonfairSync();
}
/**
* Creates an instance of {@code ReentrantLock} with the
* given fairness policy.
*
* @param fair {@code true} if this lock should use a fair ordering policy
*/
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
可重入锁
也叫递归锁,指的是同一个线程外层函数获得锁之后,内层递归函数仍能获取该锁的代码,在同一个线程外层方法获取锁的时候,在进入内层方法会自动获取锁
线程可以进入任何一个它已经拥有的锁所同步着的代码块。
可重入锁最大作用就是避免死锁。
synchronized和ReentrantLock都是可重入锁。
下面就是可重入锁,sendsms外层获得锁,sendemail内层自动获取锁,同一把锁。
自旋锁
是只尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU
cas就是自旋锁do while循环
独占锁(写锁)
该锁一次只能被一个线程所持有,ReentrantLock和synchronized都是独占所。
共享锁(读锁)
指该锁可以被多个线程所持有。
ReentrantReadWriteLock其读锁是共享锁,写锁是独占锁。
如果用ReentrantLock,不管读写都锁。
关于synchronized看我另一篇
synchronized讲解