JAVA中的鎖的概念挺多,從思想的角度,分為各種鎖。下面讓我們來分別認識一下他們。
可重入鎖、不可重入鎖
我們一般用的都是可重入鎖??芍厝腈i指的是當一個線程獲取到一個鎖后,如果再次獲取這個鎖的話,依然可以獲取到。
而不可重入鎖,指的是當一個線程獲取到一個鎖后,如果再次獲取這個鎖的話,就不能再獲取到了。不可重入鎖會導致死鎖,所以我們一般是不會使用不可重入鎖的。
公平鎖、非公平鎖
AQS框架可以實現公平鎖和非公平鎖。AQS框架中包含三個主要元素,一個是狀態status,用來表示表示鎖是否被占用;另一個是當前線程;最后一個是隊列,用來保存被阻塞的線程。
如果用來保存被阻塞線程的隊列是按順序獲取鎖的,隊首線程先獲取鎖,那么這就是公平鎖,每個線程都能夠按照進入隊列的順序獲取到鎖。
如果用來保存被阻塞線程的隊列不是按照順序來獲取鎖的,而是大家一起競爭鎖,那么就是非公平鎖,這樣可能會導致某些線程一直獲取不到鎖而被餓死。
悲觀鎖、樂觀鎖、自旋鎖
悲觀鎖和樂觀鎖也是一種不同維度的鎖的思想。
悲觀鎖指的是在執行操作之前加鎖,來保證操作只有獲取到鎖的線程才能執行。這樣的話,由于有加鎖操作,所以效率可能會低,但是保證安全。比如synchronized和ReentrantLock都是悲觀鎖。
樂觀鎖在執行之前不加鎖,而在執行的時候進行判斷,比如CAS就是典型的樂觀鎖。執行的時候先比較線程工作內存是否為最新數據,如果是最新數據才進行更新,如果不是最新數據,工作線程內存中的數據已經過期,則交給開發者去處理。
提到CAS,有人可能會想到自旋鎖。synchronized中的輕量級鎖不就是采用了CAS自旋鎖的方式么。這里,我們要區分好CAS和自旋的概念。CAS是compare and swap,即比較并交換。它是一次操作,一次比較并交換操作。而自旋指的是多次執行同樣的操作。它們兩個是不同的概念。而自旋鎖指的是用自旋的方式多次執行CAS操作。所以,CAS是樂觀鎖,而多次CAS,也就是多次執行樂觀鎖,就成了自旋鎖。
獨占鎖、共享鎖
獨占鎖、共享鎖也是思想成本的概念。
獨占鎖指的是只有一個線程可以擁有這個鎖來執行相應操作。比如:synchronized和ReentrantLock,以及讀寫鎖中的寫鎖。
共享鎖指的是可以有多個線程同時擁有這個鎖。比如:讀寫鎖中的讀鎖,是允許多個線程一同獲取到的。還有Semaphore(信號量),因為允許多個線程通過,所以也是共享鎖。
總結
之所以有這么多鎖的概念,都是從不同維度對鎖進行的分類。這些都是概念層面上的東西,可以有不同的實現方式。
而這些鎖的本質其實都是一個框架,這個框架的功能就是在合適的時機讓某一個或者某些線程執行,而另一個或者另一些線程阻塞。而Java并發庫中的鎖,讓哪個線程執行、哪個線程阻塞是由AQS來決定的,而AQS是基于共享變量和LockSupport來實現的。
沒錯,鎖就是用來控制線程阻塞和執行的一套框架。