介绍
上一篇文章我们分析了简单锁的缺点,发现简单锁竟然自己可以把自己死锁.所以可重入锁出现了,可重入锁就是为了解决自己和自己死锁的问题.锁的内部可以记住哪个线程持有锁.这样保证已经获得锁的线程不会再次获得锁
实现
我们的实现可以根据简单锁改进.
版本1
public class CustomReentrantLock1 {
    AtomicInteger atomicInteger = new AtomicInteger();
    volatile Thread curThread;
    public void lock() {
        while (!atomicInteger.compareAndSet(0, 1)) {
            if (curThread == Thread.currentThread()) break;
        }
        curThread = Thread.currentThread();
    }
    public void unLock() {
        curThread = null;
        atomicInteger.set(0);
    }
    static CustomReentrantLock1 lock = new CustomReentrantLock1();
    public static void main(String[] args) {
        lock.lock();
        methodA();
        lock.unLock();
    }
    private static void methodA() {
        lock.lock();
        //do something
        lock.unLock();
    }
复制代码以上实现是否可行?
我们仔细观察,运行,发现好像不行.代码中的例子中,调用了两次lock.lock();,而只调用一次 lock.unLock();发现就把锁了两次的lock给释放了.所以上面的实现是不正确的.我们需要有一个变量来记录一个线程调用了多少次lock.lock
版本2
在版本1之上改进:
import java.util.concurrent.atomic.AtomicInteger;
public class CustomReentrantLock2 {
    AtomicInteger atomicInteger = new AtomicInteger();
    volatile Thread curThread;
    volatile int count;
    public void lock() {
        while (!atomicInteger.compareAndSet(0, 1)) {
            if (curThread == Thread.currentThread()) {
                count += 1;
                return;
            }
            Thread.onSpinWait();//让出cpu,但是还在竞争队列里
        }
        curThread = Thread.currentThread();
        count = 1;
    }
    public void unLock() {
        if (curThread != Thread.currentThread()) return;
        count -= 1;
        if (count == 0) {
            curThread = null;
            atomicInteger.set(0);
        }
    }
    static CustomReentrantLock2 lock = new CustomReentrantLock2();
    public static void main(String[] args) {
        lock.lock();
        methodA();
        lock.unLock();
    }
    private static void methodA() {
        lock.lock();
        //do something
        lock.unLock();
    }
}
复制代码加了一个被 volatile修饰的count,这时我们的可重入锁好像就实现了.
扩展
问:我们是否还有其他的方式来实现可重入锁?是否可以用ThreadLocal来记录这些东西?是否可以使用ThreadLocal实现一个可重入锁?
答:可以
下篇文章介绍公平锁
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
    






















![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)
