java重入锁_java并发编程:可重入锁是什么?
釋義
廣義上的可重入鎖指的是可重復可遞歸調用的鎖,在外層使用鎖之后,在內層仍然可以使用,并且不發(fā)生死鎖(前提得是同一個對象或者class),這樣的鎖就叫做可重入鎖。ReentrantLock和synchronized都是可重入鎖,下面是一個用synchronized實現(xiàn)的例子:
public class ReentrantTest implements Runnable {
public synchronized void get() {
System.out.println(Thread.currentThread().getName());
set();
}
public synchronized void set() {
System.out.println(Thread.currentThread().getName());
}
public void run() {
get();
}
public static void main(String[] args) {
ReentrantTest rt = new ReentrantTest();
for(;;){
new Thread(rt).start();
}
}
}
整個過程沒有發(fā)生死鎖的情況,截取一部分輸出結果如下:
Thread-8492
Thread-8492
Thread-8494
Thread-8494
Thread-8495
Thread-8495
Thread-8493
Thread-8493
set()和get()同時輸出了線程名稱,表明即使遞歸使用synchronized也沒有發(fā)生死鎖,證明其是可重入的。
不可重入鎖
不可重入鎖,與可重入鎖相反,不可遞歸調用,遞歸調用就發(fā)生死鎖。看到一個經(jīng)典的講解,使用自旋鎖來模擬一個不可重入鎖,代碼如下:
import java.util.concurrent.atomic.AtomicReference;
public class UnreentrantLock {
private AtomicReference owner = new AtomicReference();
public void lock() {
Thread current = Thread.currentThread();
//這句是很經(jīng)典的“自旋”語法,AtomicInteger中也有
for (;;) {
if (!owner.compareAndSet(null, current)) {
return;
}
}
}
public void unlock() {
Thread current = Thread.currentThread();
owner.compareAndSet(current, null);
}
}
代碼也比較簡單,使用原子引用來存放線程,同一線程兩次調用lock()方法,如果不執(zhí)行unlock()釋放鎖的話,第二次調用自旋的時候就會產(chǎn)生死鎖,這個鎖就不是可重入的,而實際上同一個線程不必每次都去釋放鎖再來獲取鎖,這樣的調度切換是很耗資源的。稍微改一下,把它變成一個可重入鎖:
import java.util.concurrent.atomic.AtomicReference;
public class UnreentrantLock {
private AtomicReference owner = new AtomicReference();
private int state = 0;
public void lock() {
Thread current = Thread.currentThread();
if (current == owner.get()) {
state++;
return;
}
//這句是很經(jīng)典的“自旋”式語法,AtomicInteger中也有
for (;;) {
if (!owner.compareAndSet(null, current)) {
return;
}
}
}
public void unlock() {
Thread current = Thread.currentThread();
if (current == owner.get()) {
if (state != 0) {
state--;
} else {
owner.compareAndSet(current, null);
}
}
}
}
在執(zhí)行每次操作之前,判斷當前鎖持有者是否是當前對象,采用state計數(shù),不用每次去釋放鎖。
ReentrantLock中可重入鎖實現(xiàn)
這里看非公平鎖的鎖獲取方法:
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
//就是這里
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
在AQS中維護了一個private volatile int state來計數(shù)重入次數(shù),避免了頻繁的持有釋放操作,這樣既提升了效率,又避免了死鎖。
超強干貨來襲 云風專訪:近40年碼齡,通宵達旦的技術人生總結
以上是生活随笔為你收集整理的java重入锁_java并发编程:可重入锁是什么?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java的css的块_CSS块宽度不大于
- 下一篇: java程序中怎么保证多线程的运行安全_