可重入锁,就是支持重入的锁,它表示该锁能够支持一个线程对资源的重复加锁。除此之外,该锁还支持获取公平锁和非公平锁。
    在绝对的时间上,先对锁进行获取请求的一定先被满足,那么这个锁是公平锁,反之,是非公平锁。
    公平锁往往没有非公平锁的效率高,但是,并不是任何场景都是以TPS作为唯一的指标,公平锁能够减少“饥饿”的概率。

    实现重进入
    重进入是指任意线程在获取到锁后能够再次获取该锁而不会被阻塞,这需要解决两个问题:
    1)线程再次获取锁。锁需要识别获取锁的线程,如果是则再次获取成功
    2)锁的最终释放。线程重复n次获取了锁,随后在第n次释放锁后,其他线程能够获取到该锁。锁的最终释放要求锁对于获取进行计数自增,计数表示当前锁被重复获取的次数,而锁释放时,计数自减,当计数等于0时表示锁已经成功释放。

    公平与非公平获取锁的区别
    公平性与否是针对获取锁而言的,如果一个锁是公平的,那么获取锁的顺序就应该符合请求的绝对顺序,也就是FIFO。

    非公平锁的获取

    1. final boolean nonfairTryAcquire(int acquires) {
    2. final Thread current = Thread.currentThread();
    3. int c = getState();
    4. if (c == 0) {
    5. //cas获取锁
    6. if (compareAndSetState(0, acquires)) {
    7. //设置当前线程为排它锁拥有线程
    8. setExclusiveOwnerThread(current);
    9. return true;
    10. }
    11. }
    12. //如果当前线程是拥有排它锁的线程
    13. else if (current == getExclusiveOwnerThread()) {
    14. int nextc = c + acquires;
    15. if (nextc < 0) // overflow
    16. throw new Error("Maximum lock count exceeded");
    17. //计数器自增
    18. setState(nextc);
    19. return true;
    20. }
    21. return false;
    22. }

    公平锁的获取

    1. protected final boolean tryAcquire(int acquires) {
    2. final Thread current = Thread.currentThread();
    3. int c = getState();
    4. if (c == 0) {
    5. if (!hasQueuedPredecessors() &&
    6. compareAndSetState(0, acquires)) {
    7. setExclusiveOwnerThread(current);
    8. return true;
    9. }
    10. }
    11. else if (current == getExclusiveOwnerThread()) {
    12. int nextc = c + acquires;
    13. if (nextc < 0)
    14. throw new Error("Maximum lock count exceeded");
    15. setState(nextc);
    16. return true;
    17. }
    18. return false;
    19. }
    1. public final boolean hasQueuedPredecessors() {
    2. // 这个的正确性取决于头部在尾部和头部之前被初始化。如果当前线程在队列中的第一个,则它是准确的。
    3. Node t = tail; // Read fields in reverse initialization order
    4. Node h = head;
    5. Node s;
    6. return h != t &&
    7. ((s = h.next) == null || s.thread != Thread.currentThread());
    8. }

    锁的释放

    1. protected final boolean tryRelease(int releases) {
    2. int c = getState() - releases;
    3. //拥有锁的线程不是当前线程,报错
    4. if (Thread.currentThread() != getExclusiveOwnerThread())
    5. throw new IllegalMonitorStateException();
    6. boolean free = false;
    7. if (c == 0) {
    8. //计数为0时,释放锁,将拥有锁的线程设置为null
    9. free = true;
    10. setExclusiveOwnerThread(null);
    11. }
    12. //更新计数
    13. setState(c);
    14. return free;
    15. }