概述
全称是 AbstractQueuedSynchronizer ,是阻塞式锁和相关的同步器工具的框架
核心方法
tryAcquire ( )
tryRelease ( )
tryAcquireShared ( )
tryReleaseShared ( )
isHeldExclusively ( )
特点
用 state 属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取锁和释放锁
getState - 获取 state 状态
setState - 设置 state 状态
compareAndSetState - cas 机制设置 state 状态
独占模式是只有一个线程能够访问资源,而共享模式可以允许多个线程访问资源
独占锁
公平锁:按照线程在队列中的排队顺序,先到者先拿到锁
非公平锁:当线程要获取锁时,无视队列顺序直接去抢锁,谁抢到就是谁的
ReentrantLock 、ReentrantReadWriteLock. WriteLock
protected boolean tryAcquire ( int arg)
protected boolean tryRelease ( int arg)
共享锁
ReentrantReadWriteLock. ReadLock 、CountDownLatch 、
CyclicBarrier 、Semaphore
protected int tryAcquireShared ( int arg)
protected boolean tryReleaseShared ( int arg)
设计思想
while ( state 状态不允许获取《未获得锁》) {
if ( 队列中还没有此线程) {
入队并阻塞
}
}
《获得锁》
当前线程出队
if ( state 状态允许了) {
恢复阻塞的线程( s)
}
要点
原子维护 state 状态
阻塞及恢复线程
维护队列
state 使用 volatile 配合 cas 保证其修改时的原子性
state 使用了 32 bit int 来维护同步状态,因为当时使用 long 在很多平台下测试
的结果并不理想
自定义锁(不可重入锁)
思想: 使用Lock 接口,底层实现使用自定义同步器
class MyLock implements Lock {
class MySync extends AbstractQueuedSynchronizer {
@Override
protected boolean tryAcquire ( int arg) {
if ( compareAndSetState ( 0 , 1 ) ) {
setExclusiveOwnerThread ( Thread . currentThread ( ) ) ;
return true ;
}
return false ;
}
@Override
protected boolean tryRelease ( int arg) {
setExclusiveOwnerThread ( null ) ;
setState ( 0 ) ;
return true ;
}
@Override
protected boolean isHeldExclusively ( ) {
return getState ( ) == 1 ;
}
public Condition newCondition ( ) {
return new ConditionObject ( ) ;
}
}
private MySync sync = new MySync ( ) ;
@Override
public void lock ( ) {
sync. acquire ( 1 ) ;
}
@Override
public void lockInterruptibly ( ) throws InterruptedException {
sync. acquireInterruptibly ( 1 ) ;
}
@Override
public boolean tryLock ( ) {
return sync. tryAcquire ( 1 ) ;
}
@Override
public boolean tryLock ( long time, TimeUnit unit) throws InterruptedException {
return sync. tryAcquireNanos ( 1 , unit. toNanos ( time) ) ;
}
@Override
public void unlock ( ) {
sync. release ( 1 ) ;
}
@Override
public Condition newCondition ( ) {
return sync. newCondition ( ) ;
}
}
@Slf4j ( topic = "c.TestAqs" )
public class TestAqs {
public static void main ( String [ ] args) {
MyLock lock = new MyLock ( ) ;
new Thread ( ( ) -> {
lock. lock ( ) ;
try {
log. debug ( "locking..." ) ;
sleep ( 1 ) ;
} finally {
log. debug ( "unlocking..." ) ;
lock. unlock ( ) ;
}
} , "t1" ) . start ( ) ;
new Thread ( ( ) -> {
lock. lock ( ) ;
try {
log. debug ( "locking..." ) ;
} finally {
log. debug ( "unlocking..." ) ;
lock. unlock ( ) ;
}
} , "t2" ) . start ( ) ;
}
}
17 : 38 : 08.443 c. TestAqs [ t1] - locking. . .
17 : 38 : 09.450 c. TestAqs [ t1] - unlocking. . .
17 : 38 : 09.450 c. TestAqs [ t2] - locking. . .
17 : 38 : 09.450 c. TestAqs [ t2] - unlocking. . .