在單進程的系統中,當存在多個線程能夠同時改變某個變量時,就須要對變量或代碼塊作同步,使其在修改這種變量時可以線性執行消除併發修改變量。
而同步的本質是經過鎖來實現的。爲了實現多個線程在一個時刻同一個代碼塊只能有一個線程可執行,那麼須要在某個地方作個標記,這個標記必須每一個線程都能看到,當標記不存在時能夠設置該標記,其他後續線程發現已經有標記了則等待擁有標記的線程結束同步代碼塊取消標記後再去嘗試設置標記。這個標記能夠理解爲鎖。
不一樣地方實現鎖的方式也不同,只要能知足全部線程都能看獲得標記便可。如java中synchronize是在對象頭設置標記,Lock接口的實現類基本上都只是某一個volitile修飾的int型變量其保證每一個線程都能擁有對該int的可見性和原子修改,linux內核中也是利用互斥量或信號量等內存數據作標記。java
分佈式鎖是控制分佈式系統之間同步訪問共享資源的一種方式。在分佈式系統中,經常須要協調他們的動做。若是不一樣的系統或是同一個系統的不一樣主機之間共享了一個或一組資源,那麼訪問這些資源的時候,每每須要互斥來防止彼此干擾來保證一致性,在這種狀況下,便須要使用到分佈式鎖。linux
基於數據庫樂觀鎖實現:
樂觀鎖一般實現基於數據版本號(version)的記錄機制實現的,在修改數據庫前獲取版本號,修改數據時與獲取版本號不一致則拋出異常(修改數據時切記對版本號進行+1)git
使用redis的setnx()、get()、getset()方法,用於分佈式鎖redis
利用臨時節點與 watch 機制。每一個鎖佔用一個普通節點 /lock,當須要獲取鎖時在 /lock 目錄下建立一個臨時節點,建立成功則表示獲取鎖成功,失敗則 watch/lock 節點,有刪除操做後再去爭鎖。臨時節點好處在於當進程掛掉後能自動上鎖的節點自動刪除即取消鎖spring
基於redisson實現的spring boot starter分佈式鎖框架,實現了可重入鎖、公平鎖、聯鎖、紅鎖、讀寫鎖等經常使用鎖的方式,並支持集羣模式下的redis。數據庫
爲何推薦此項目?緩存
引入maven依賴便可使用併發
<dependency> <groupId>io.gitee.tooleek</groupId> <artifactId>lock-spring-boot-starter</artifactId> <version>1.1.0</version> </dependency>