重入锁

ReentrantLock:重入锁,它是唯一一个实现了 Lock 接口的类。

synchronized 和 ReentrantLock 都是可重入锁

独占锁:ReentrantLock、ReentrantReadWriteLock.WriteLock
共享锁:ReentrantReadWriteLock.ReadLock、CountDownLatch、CyclicBarrier、Semaphore
其实现方式为:
独占锁实现的是tryAcquire(int)、tryRelease(int)
共享锁实现的是tryAcquireShared(int)、tryReleaseShared(int)

实现原理:

是通过为每个锁关联一个请求计数和一个占有它的线程。
当计数为0时,认为锁是未被占有的。
线程请求一个未被占有的锁时,jvm讲记录锁的占有者,并且讲请求计数器置为1 。
如果同一个线程再次请求这个锁,计数将递增;
每次占用线程退出同步块,计数器值将递减。
直到计数器为0,锁被释放。

重入锁指的是线程在获得锁之后,再次获取该锁不需要阻塞,而是直接关联一次计数器增加重入次数。

比如调用 demo1 方法获得了当前的对象锁,然后在这个方法中再去调用demo2,
demo2 中的存在同一个实例锁,这个时候当前线程会因为无法获得
demo2 的对象锁而阻塞, 如果 不是 重入锁 就会产生死锁。

重入锁的设计目的

重入锁的设计目的是避免线程的死锁。

public class ReentrantDemo{
  public synchronized void demo1(){
    System.out.println("begin:demo1");
    demo2();
  }
  public void demo2(){
    System.out.println("begin:demo1");
    synchronized (this){
    }
  }
  public static void main(String[] args) {
    ReentrantDemo rd=new ReentrantDemo();
    new Thread(rd.demo1()).start();
        }
}
public class AtomicDemo {
  private static int count=0;
  static Lock lock=new ReentrantLock();
  public static void inc(){
       //重入锁
    lock.lock();
    try {
      Thread.sleep(2);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    count++;
    lock.unlock();
  }
  public static void main(String[] args) throws InterruptedException {
     for(int i=0;i<200;i++){
      new Thread(()->{AtomicDemo.inc();}).start();
     }
    Thread.sleep(4000);System.out.println("result:"+count);
  }
}