一、可重入鎖與不可重入鎖的區別
可重入鎖和不可重入鎖的最大區別在於,可重入鎖允許同一個線程在獲得鎖之後再次獲得該鎖,而不可重入鎖不允許。
在使用不可重入鎖時,如果一個線程已經獲得該鎖,那麼在該線程釋放該鎖之前,其他所有線程都無法獲得這個鎖。而在使用可重入鎖時,如果一個線程已經獲得鎖,那麼在該線程釋放該鎖之前,它可以再次獲得該鎖而不會被阻塞。
二、可重入鎖的使用場景
可重入鎖通常應用於遞歸或者嵌套的代碼中。在代碼嵌套調用的過程中,如果使用不可重入鎖,那麼程序將會阻塞,可能會導致死鎖現象的發生。
舉例來說,在使用不可重入鎖時,如果在一個線程已經獲得鎖的情況下,又嘗試獲得該鎖,那麼這個線程將會被一直阻塞,直到另外一個線程釋放該鎖。而在使用可重入鎖時,同一個線程可以多次獲得鎖,因此不會導致死鎖現象的發生。
三、可重入鎖的實現原理
可重入鎖最常用的實現方式是通過計數器來實現的,每次獲得鎖時,計數器加1,每次釋放鎖時,計數器減1。只有當計數器為0時,其他線程才有機會獲得該鎖。這樣就能夠保證同一個線程可以多次獲得該鎖,而其他線程只有在該鎖被徹底釋放時才能獲得該鎖。
四、synchronized可重入鎖
在Java語言中,synchronized關鍵字是一種可重入鎖。這意味著如果一個線程已經獲得了某個對象上的synchronized鎖,那麼它可以再次獲得該對象鎖而不會被阻塞。
synchronized鎖的實現方式並不是通過計數器來實現的。它是通過線程持有的對象監視器(也可以稱為鎖對象)來實現的。當線程請求進入一段同步代碼時,如果該鎖沒有被其他線程佔用,那麼該線程會獲得該鎖,同時鎖對象的計數器會+1。如果同一線程再次請求該鎖,那麼線程可以再次獲得該鎖,同時計數器也會再次+1。當線程執行完同步代碼塊並釋放鎖時,該線程持有的鎖對象的計數器會-1。只有當該計數器的值為0時,鎖對象才會被解鎖,這樣其他線程才有機會獲得該鎖。
五、可重入鎖和不可重入鎖的區別
1、可重入鎖允許同一個線程在獲得鎖之後再次獲得該鎖,而不可重入鎖不允許。
2、在使用不可重入鎖時,如果一個線程已經獲得該鎖,那麼在該線程釋放該鎖之前,其他所有線程都無法獲得這個鎖。而在使用可重入鎖時,如果一個線程已經獲得鎖,那麼在該線程釋放該鎖之前,它可以再次獲得該鎖而不會被阻塞。
3、可重入鎖通常用於遞歸嵌套的代碼中,而不可重入鎖一般只用於獨佔式地獲得資源。
示例代碼
// 可重入鎖的示例 import java.util.concurrent.locks.ReentrantLock; public class ReentrantLockDemo { private static final ReentrantLock lock = new ReentrantLock(); public static void main(String[] args) { for (int i = 0; i < 5; i++) { new Thread(new Runnable() { @Override public void run() { work(); } }).start(); } } private static void work() { lock.lock(); try { System.out.println(Thread.currentThread().getName() + "獲得了鎖"); nestedWork(); } finally { lock.unlock(); } } private static void nestedWork() { lock.lock(); try { System.out.println(Thread.currentThread().getName() + "再次獲得了鎖"); } finally { lock.unlock(); } } } // 不可重入鎖的示例 import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class NonReentrantLockDemo { private static final Lock lock = new ReentrantLock(); public static void main(String[] args) { new Thread(new Runnable() { @Override public void run() { work(); } }, "Thread-A").start(); new Thread(new Runnable() { @Override public void run() { work(); } }, "Thread-B").start(); } private static void work() { lock.lock(); try { System.out.println(Thread.currentThread().getName() + "獲得了鎖"); nestedWork(); } finally { lock.unlock(); } } private static void nestedWork() { lock.lock(); try { System.out.println(Thread.currentThread().getName() + "嘗試獲得鎖但被阻塞了"); } finally { lock.unlock(); } } }
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/199136.html