樂觀鎖/悲觀鎖
公平鎖/非公平鎖
獨享鎖/共享鎖
互斥鎖/讀寫鎖
可重入鎖(又名遞歸鎖)
自旋鎖
分段鎖
偏向鎖/輕量級鎖/重量級鎖
樂觀鎖/悲觀鎖
樂觀鎖與悲觀鎖不是指兩種特定類型的鎖, 而是人們針對并發(fā)同步的角度定義出來的兩種概念
樂觀鎖: 顧名思義, 樂觀, 認為拿到的數(shù)據(jù)沒有被別的線程修改, 不上鎖, 使用版本號來標記當前拿到的數(shù)據(jù), 需要跟新數(shù)據(jù)時, 再去比較當前版本號與期望版本號是否一致, 常用的樂觀鎖有數(shù)據(jù)庫的version, jdk1.8并發(fā)包中的atomin下的原子操作類, 的CAS實現(xiàn)
悲觀鎖:顧名思義, 悲觀, 認為拿到的數(shù)據(jù)會被別的線程修改, 所以拿數(shù)據(jù)的時候先上鎖, 然后進行操作, 操作完成釋放鎖, 常用的悲觀鎖數(shù)據(jù)庫中for update, java synchronezed關鍵字, ReetrantLock 加鎖
公平鎖/非公平鎖
公平鎖是指多個線程按照申請的順序來獲取鎖, 非公平鎖不按照申請的順序來獲取鎖
synchronezed關鍵字, ReetrantLock 默認構造器創(chuàng)建的對象都是非公平鎖
ReetrantLock(true) 創(chuàng)建的是公平鎖
獨享鎖/共享鎖
獨享鎖是指該鎖一次只能被一個線程所持有, 共享鎖是指一個該鎖可以被過個線程所持有
synchronezed關鍵字, ReetrantLock 都是獨享鎖
ReadWriteLick其讀是共享鎖, 寫是獨有鎖
互斥鎖/讀寫鎖
獨享鎖/共享鎖是一致廣義的說法, 互斥鎖/讀寫鎖就是具體的實現(xiàn)
synchronezed關鍵字, ReetrantLock 都是獨享鎖
ReadWriteLock其讀是共享鎖, 寫是獨有鎖
可重入鎖(又名遞歸鎖)
線程可以進入任何一個它已經(jīng)擁有的鎖所同步的代碼塊中, 簡單來說就是線程在外層方法獲取鎖, 進入內層方法會自動獲取鎖, synchronezed關鍵字, ReetrantLock都是可重入鎖, 好處是避免死鎖.
自旋鎖
自旋鎖是指嘗試獲取鎖的線程不會立即阻塞,而是采用循環(huán)的方式去嘗試獲取鎖,這樣的好處是減少線程上下文切換的消耗,缺點是循環(huán)會消耗CPU。
分段鎖
分段鎖是一種鎖的設計, 并不是一種具體的鎖, 最有名的分段鎖設計是ConcurrentHashMap, 將map容器分段出多個Entry數(shù)組, 在push炒作時先確認哪個數(shù)據(jù), 然后再進行加鎖操作.
synchronized與Lock的區(qū)別
- synchronized 是屬于JVM層面的關鍵字, Lock是api層面的鎖
- synchronized無需手動去釋放鎖, Lock需要手動釋放鎖(可能導致死鎖)
- synchronized不可中斷, ReentrantLock可中斷
- synchronized非公平鎖, ReentrantLock可以設置為公平非公平鎖
- synchronized無法綁定多個Condition, 無法實現(xiàn)分組喚醒, ReentrantLock可以實現(xiàn)
死鎖分析
死鎖的原因
線程A持有鎖A, 嘗試獲取線程B, 線程B持有鎖A嘗試獲取線程B.
代碼分析
public class Resource implements Runnable {
private String lockA = null;
private String lockB = null;
public Resource(String lockA, String lockB) {
this.lockA = lockA;
this.lockB = lockB;
}
public void run() {
synchronized (lockA) {
System.out.println("===" + lockA + "===");
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e){
e.printStackTrace();
}
synchronized (lockB){
System.out.println("===" + lockB + "====");
}
}
}
}
public class LockTest {
public static void main(String[] args) {
String lockA = "lockA";
String lockB = "lockB";
new Thread(new Resource(lockA, lockB), "A").start();
new Thread(new Resource(lockB, lockA), "B").start();
}
}
執(zhí)行效果: 程序一直沒有停止

