package com.yunding.concurrent;
/**
* 可重入锁的原理: 如果某个线程视图获取一个已经由它自己持有的锁时,那么这个请求会立刻成功,并且会将这个锁的计数值加 1,
* 而当线程退出同步代码块(synchronized(){})时,计数器将会递减,当计数器的等于0时,锁释放
* 如果没有可重入锁的支持,在第二次企图获取锁时会进入死锁状态
* java.util.concurrent包下有ReentrantLock可以直接使用,不用自己实现可重入锁
*
* @author beOkWithAnything
*
*/
public class LockTest {
ReLock lock = new ReLock();
void a() {
System.out.println(lock.getHoldCount());
lock.lock();
System.out.println(lock.getHoldCount());
doSomething();
lock.unLock();
System.out.println(lock.getHoldCount());
}
void doSomething() {
lock.lock();
System.out.println(lock.getHoldCount());
// .....
lock.unLock();
System.out.println(lock.getHoldCount());
}
public static void main(String[] args) {
LockTest test = new LockTest();
test.a();
}
}
class ReLock {
// 是否被占用
private boolean isLocked = false;
// 存储占用锁的线程
private Thread lockedBy = null;
// 当前对象被锁的次数
private int holdCount = 0;
// 使用锁: 如果是被自己锁的,可以直接用
public synchronized void lock() {
Thread thread = Thread.currentThread();
// 如果不是被自己锁的
while (isLocked && lockedBy != thread) {
try {
// 等待
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 已经被锁
isLocked = true;
// 锁被thread持有
lockedBy = thread;
// 被锁一次
holdCount++;
}
// 释放锁
public synchronized void unLock() {
// 如果是被当前线程锁的
if (Thread.currentThread() == lockedBy) {
holdCount--;
// 计数器的等于0时,锁释放
if (holdCount == 0) {
lockedBy = null;
isLocked = false;
notify();
}
}
}
public int getHoldCount() {
return holdCount;
}
}