自定义锁,可以通过实现Lock接口,重写相应的方法即可。代码如下,
private boolean isLocked = false;
private Thread lockBy = null;
private int lockCount = 0;
@Override
public synchronized void lock() {
Thread currentThread = Thread.currentThread();
while (isLocked && currentThread != lockBy) {
//第一个线程抢到,进来后,isLocked=false,不需要wait,不需要while循环
//第二个线程来了,如果已经锁了,并且还是锁的那个线程,也不wait,反之,需要wait
//因此,条件是没有锁的时候,以及锁了以后还是同一个线程,不需wait
//这里使用while,是为了防止wait被虚拟唤醒,即线程由于某些特殊情况,不是被notify或者notifyAll所唤醒,所以还需要再次判断条件是否成立
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
isLocked = true;
lockBy = currentThread;
lockCount++;
}
@Override
public synchronized void unlock() {
//这里判断是否是锁的线程,是为了防止Lock对象的unlock方法乱用,在非没有竞争锁的线程中使用了unlock方法
if (lockBy == Thread.currentThread()) {
lockCount--;
if (lockCount == 0) {
notify();
isLocked = false;
}
}
}
注意,几个属性,isLocked,lockBy,lockCount
,实现可重入的效果的锁。lockCount
统计了获得锁的线程,重入了多少次,因此,在unlock的时候,要看释放锁多少次,即,重入多少次,就释放多少次,否则依旧获得锁,无法notify其他阻塞的线程。