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()方法后,第二个线程才被唤醒,继续执行。这就是可重入锁的特点。