鎖、分布式鎖、無鎖分布式無鎖
為什麼要有鎖?
保證資源線程安全,簡單說就是在多線程情況下不會亂。
鎖的分類
- JVM鎖:類鎖、對象鎖、偏向、公平、重入、死鎖
- 分布式鎖:Redis、DB、zookeeper
類鎖和對象鎖的差別
類鎖
- 方法中寫着static synchronized
- 整個Object.class隻有一個鎖,所有對象隻有一個鎖
對象鎖
- 方法聲明中隻寫synchronized
- Object的執行個體化對象object1、object2、object3,各有一個自己的鎖
JVM鎖如何實作
同步方法
public synchronized void save(){}
注: synchronized關鍵字也可以修飾靜态方法,此時如果調用該靜态方法,将會鎖住整個類
同步塊
synchronized(object){
}
注:同步是一種高開銷的操作,是以應該盡量減少同步的内容。
volatile
- volatile關鍵字為域變量的通路提供了一種免鎖機制,
- 使用volatile修飾域相當于告訴虛拟機該域可能會被其他線程更新,
- 是以每次使用該域就要重新計算,而不是使用寄存器中的值
- volatile不會提供任何原子操作,它也不能用來修飾final類型的變量
注:這個雖然能實作線程安全,但是沒有原子性,如(i++)
重入鎖:ReenreantLock
- ReentrantLock() : 建立一個ReentrantLock執行個體
- lock() : 獲得鎖
- unlock() : 釋放鎖
注:ReentrantLock()還有一個可以建立公平鎖的構造方法,但由于能大幅度降低程式運作效率,不推薦使用
并發集合、并發工具類
- ConcurrentHashMap
- CopyOnWriteArrayList
- 并發工具類:java.util.concurrent(JUC)
原子操作:Atomic
使用局部變量實作線程同步:ThreadLocal
分布式鎖
Redis
- 單線程,速度快,單點
- 加鎖:setNx()、取鎖:getNx()
- 或者setString也可以實作分布式鎖
DB
悲觀鎖:select * from table for update(Quartz)
樂觀鎖:加多個version字段
Zookeeper:待學習。。。。。
無鎖、分布式無鎖
同樣是使用redis實作,用它的自增功能,jedis.incr()