原创

Java中可重入锁与不可重入锁

可重入锁

概念

同一个线程中可多次获取同一把锁,无需等待其锁释放。如ReentrantLock,synchronized等。

使用示例

import java.util.concurrent.locks.ReentrantLock;

/**
 * @author weilai
 * @email 352342845@qq.com
 * @date 2020/3/23 12:58 下午
 */
public class DemoLock {

    public static ReentrantLock lock = new ReentrantLock();

    public static void accessResource() {
        lock.lock();
        try {
            System.out.println(lock.getHoldCount());
            System.out.println("获取资源");
            if (lock.getHoldCount() < 5) {
                accessResource();
            }
            System.out.println(lock.getHoldCount());
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        accessResource();
    }

}

output:

1
获取资源
2
获取资源
3
获取资源
4
获取资源
5
获取资源
5
4
3
2
1

可重入锁核心源码分析:

核心原理:

file
file

核心原理采用AQS原理实现。

具体查看:ReentrantLock核心源码分析

不可重入锁

概念

同一个线程在获取锁的情况下,如需再次获取这把锁,仍需要等待其锁释放。

不可重入锁核心源码分析:

不判断是否为自己,状态为0的时候才可以加锁,否则等待。

核心原理采用AQS原理实现。下面为AQS自己实现的注释中示例代码:

// Acquires the lock if state is zero
public boolean tryAcquire(int acquires) {

  // 断言判断传入参数必须为1,不存在可重入增加的情况,加锁只能为1
  assert acquires == 1; // Otherwise unused
  // 尝试加锁,成功返回true,失败返回false
  if (compareAndSetState(0, 1)) {
    setExclusiveOwnerThread(Thread.currentThread());
    return true;
  }
  return false;
}

// Releases the lock by setting state to zero
protected boolean tryRelease(int releases) {

  // 断言判断传入参数必须为1,不存在可重入增加的情况,加锁只能为1
  assert releases == 1; // Otherwise unused
  if (getState() == 0) throw new IllegalMonitorStateException();
  setExclusiveOwnerThread(null);
  // 释放时直接改为0,不需要减1操作
  setState(0);
  return true;
}
正文到此结束
本文目录