天天看點

鎖、分布式鎖、無鎖分布式無鎖

鎖、分布式鎖、無鎖分布式無鎖

為什麼要有鎖?

      保證資源線程安全,簡單說就是在多線程情況下不會亂。

鎖的分類

  • JVM鎖:類鎖、對象鎖、偏向、公平、重入、死鎖
  • 分布式鎖:Redis、DB、zookeeper

類鎖和對象鎖的差別

類鎖

  1. 方法中寫着static synchronized
  2. 整個Object.class隻有一個鎖,所有對象隻有一個鎖

對象鎖

  1. 方法聲明中隻寫synchronized
  2. Object的執行個體化對象object1、object2、object3,各有一個自己的鎖

JVM鎖如何實作

同步方法

public synchronized void save(){}

注: synchronized關鍵字也可以修飾靜态方法,此時如果調用該靜态方法,将會鎖住整個類

同步塊

synchronized(object){ 

}

注:同步是一種高開銷的操作,是以應該盡量減少同步的内容。 

volatile

  1. volatile關鍵字為域變量的通路提供了一種免鎖機制, 
  2. 使用volatile修飾域相當于告訴虛拟機該域可能會被其他線程更新, 
  3. 是以每次使用該域就要重新計算,而不是使用寄存器中的值 
  4. volatile不會提供任何原子操作,它也不能用來修飾final類型的變量 

注:這個雖然能實作線程安全,但是沒有原子性,如(i++)

重入鎖:ReenreantLock

  1. ReentrantLock() : 建立一個ReentrantLock執行個體 
  2. lock() : 獲得鎖 
  3. 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()