Java中常用的重入鎖
java中重入鎖的定義是指可重複、遞歸調用的鎖,在得到同一個對象或類的前提下,外層使用鎖之後,在內層中依然可是使用且不會發生死鎖。其中最常見的關鍵字是synchronize和reentrantLock這兩個。
使用synchronize實現
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
public class MyLock implements Lock {
private boolean isLocked = false;
private Thread lockBy = null;
private int lockCount = 0;
@Override
public synchronized void lock() {
// ...
Thread currentThread = Thread.currentThread(); // Thread-0
while (isLocked && currentThread != lockBy) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
isLocked = true;
lockBy = currentThread;
lockCount++; // 1 2
}
@Override
public synchronized void unlock() {
if (lockBy == Thread.currentThread()) {
lockCount--; // 1 0
if (lockCount == 0) {
notify();
isLocked = false;
}
}
}
@Override
public void lockInterruptibly() throws InterruptedException {
}
@Override
public boolean tryLock() {
return false;
}
@Override
public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
// TODO Auto-generated method stub
return false;
}
@Override
public Condition newCondition() {
// TODO Auto-generated method stub
return null;
}
}
public class Sequence {
private MyLock lock = new MyLock();
private int value;
public int getNext() {
lock.lock();
value++;
lock.unlock();
return value;
}
public static void main(String[] args) {
Sequence s = new Sequence();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println(s.getNext());
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println(s.getNext());
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println(s.getNext());
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println(s.getNext());
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
System.out.println(s.getNext());
}
}
}).start();
}
}
當第一個線程執行getNext()方法,得到了鎖,使lockBy等於當前線程,也就是說,執行的這個方法的線程獲得了這個鎖,每次while循環都會對lockCount變量加一,即當前獲得鎖的數量加一;當線程調用unlock()釋放鎖後,lockCount變量減一,當釋放了所有的鎖之後,才執行notify()方法喚醒線程。如果在執行這個方法時,有第二個線程想要執行這個方法,因爲lockBy不等於該線程,導致第二個線程進入了循環,不斷執行wait()方法。只有當第一個線程釋放了所有的鎖,並執行了notify()方法後,第二個線程才被喚醒,繼續執行。這就是可重入鎖的特點。