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);
}
}