java中的各種鎖性能比較及原理

java中的各種鎖性能比較及原理

多線程的緣由

進程間的切換耗費的代價太大,因此需要一種花銷小,切換快的多任務操作方式。

一個進程中可以同時運行多個線程,彼此之間使用相同的地址空間,共享大部分數據。啟動一個線程所花費的空間遠小於啟動一個進程所花費的空間。

由於多個線程共享所屬進行的資源和地址空間,那麼當多線程要同時訪問某個資源時就存在加鎖的問題。

常見的鎖有:

  • synchronized
  • ReentrantLock
  • Semaphore
  • AtomicInteger

synchronized

synchronized機制是給共享資源上鎖,只有拿到鎖的線程才可以訪問共享資源,這樣就可以強制使得對共享資源的訪問都是順序的。synchronized實現的機理依賴於軟件層面上的JVM。

在多線程應用程序中使用該關鍵字,實現方便,後續工作由JVM來完成,可靠性高。只有在確定鎖機制是當前多線程程序的性能瓶頸時,才考慮使用其他機制,如ReentrantLock等

ReentrantLock

可重入鎖,顧名思義,這個鎖可以被線程多次重複進入進行獲取操作。

ReentantLock繼承接口Lock並實現了接口中定義的方法,除了能完成synchronized所能完成的所有工作外,還提供了諸如可響應中斷鎖、可輪詢鎖請求、定時鎖等避免多線程死鎖的方法。

Lock實現的機理依賴於特殊的CPU指定,可以認為不受JVM的約束,並可以通過其他語言平臺來完成底層的實現。在併發量較小的多線程應用程序中,ReentrantLock與synchronized性能相差無幾,但在高併發量的條件下,synchronized性能會迅速下降幾十倍,而ReentrantLock的性能卻能依然維持一個水準。

與synchronized會被JVM自動解鎖機制不同,ReentrantLock加鎖後需要手動進行解鎖。為了避免程序出現異常而無法正常解鎖的情況,使用ReentrantLock必須在finally控制塊中進行解鎖操作。

Semaphore

上述兩種鎖機制類型都是“互斥鎖”,學過操作系統的都知道,互斥是進程同步關係的一種特殊情況,相當於只存在一個臨界資源,因此同時最多隻能給一個線程提供服務。但是,在實際複雜的多線程應用程序中,可能存在多個臨界資源,這時候我們可以藉助Semaphore信號量來完成多個臨界資源的訪問。

Semaphore基本能完成ReentrantLock的所有工作,使用方法也與之類似,通過acquire()與release()方法來獲得和釋放臨界資源。

Semaphore的鎖釋放操作也由手動進行,因此與ReentrantLock一樣,為避免線程因拋出異常而無法正常釋放鎖的情況發生,釋放鎖的操作也必須在finally代碼塊中完成。

AtomicInteger

i++等運算不具有原子性,是不安全的線程操作之一。JVM為此類操作特意提供了一些同步類,使得使用更方便,且使程序運行效率變得更高通過相關資料顯示,通常AtomicInteger的性能是ReentantLock的好幾倍。

java中的各種鎖性能比較及原理


分享到:


相關文章: