synchronized和reentrantLock以及reentrantReadWriteLock都是java用来实现同步控制的三方法,在比较它们之前,需要对reentrantLock和reentrantReadWriteLock的父类AQS(AbstractQueuedSynchronizer)做个大概的讲述.
一 AQS是什么
AQS是java实现锁和同步器的基础,它维持了一个volatite修饰的字段state和一个双向队列。state为0代码锁未被占用,1代表锁已经被占用。当线程申请不到锁时,阻塞后加入到队列后。等待占有锁的线程释放锁,它再去竞争。reentrantLock和reentrantReadWriteLock就是基于AQS实现的类
二 synchronized和reentrantLock和区别是
1 reentrantLock是个类,synchronized是关键字。
2 synchronized枷锁和解锁不需要显示声明。reentrantLock需要lock()加锁,完了后unlock()解锁
3 reentrantLock更适用于锁竞争激烈的时候,因为不存在锁升级
4 synchronized基于objectmonitor实现,reentrantLock基于AQS实现,
5 reentrantLock功能更全面,它可以指定锁是否公平,锁的等待时间,是否可重入
6 synchronized是基于对象的。在静态方法中的synchronized关键字,是对class枷锁,非静态方法,则是对对象枷锁
三 reentrantLock和reentrantReadWriteLock(可重入锁)的区别
ReentrantLock
是一个排他锁,它只能被一个线程锁定和解锁,所以在同一时刻只能有一个线程执行被锁定的代码块。ReentrantLock
除了具有 synchronized 相同的互斥能力外,还支持可中断锁、可限时锁和公平锁等特性,具有更灵活的使用方式。
ReentrantReadWriteLock
是一个读写锁,允许多个线程同时读共享变量,但是只允许一个线程写共享变量,即写操作是互斥的。在没有写操作的时候,多个线程可以同时获得读锁,从而提高并发访问效率。相对于 ReentrantLock
,ReentrantReadWriteLock
更适合读多写少的场景。
四 reentrantReadWriteLock的大概原理
reentrantReadWriteLock的state分为两个部分,高16记录占有读锁的线程个数,低16位记录写锁的占用情况。每加一次读锁,高16位都会加一,每释放一个读锁,高16位减一