AQS是jdk中的一个类:AbstractQueuedSynchronizer,很多并发容器底层是由这个类来实现的。它定义了多个线程访问资源的一个同步类容器。比如:ReentrantLock/Semaphore/CountDownLatch。
AQS里面维护了一个共享的参数private volatile int state,以及一个先进先出的线程等待队列,访问state有3种方式:
getState();
setState();
compareAndSetState();
AQS定义了两种资源共享方式:
Exclusive:独占的,只有一个线程能执行,如ReentrantLock
Share:共享,多个线程可以同时执行,如CountDownLatch/Semaphore
AQS中提供的几个方法:
tryAcquire(int):独占方式,尝试获取资源,成功返回true,失败返回false。
tryRelease(int):独占方式,尝试释放资源,成功返回true,失败返回false。
tryAcquireShare(int):共享的方式,尝试获取资源。负数表示失败,0表示成功,但是没有剩余资源了,正数表示成功而且还有剩余资源。
tryReleaseShare(int):共享方式,尝试释放资源,成功返回true,失败返回false。
ReentrantLock:它是重入锁,也就是它可以获取锁多次,每次获取state值都会+1,它的state值从0开始,所以要释放锁也要多次释放,因为它是独占的,一个线程获取到后,其他线程只能等待。
以ReentrantLock为例:
import java.util.concurrent.locks.ReentrantLock;
public class UseReentrantLock{
private ReentrantLock reentrantLock = new ReentrantLock();
public void method() {
reentrantLock.lock();
try {
System.err.println("当前线程 " + Thread.currentThread().getName() + " 进入...");
Thread.sleep(3000);
System.err.println("当前线程 " + Thread.currentThread().getName() + " 推出...");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}
public static void main(String[] args) {
UseReentrantLock useReentrantLock = new UseReentrantLock();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
useReentrantLock.method();
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
useReentrantLock.method();
}
}, "t2");
t1.start();
t2.start();
}
}
开启两个线程,都执行method方法,method方法使用了ReentrantLock加锁,测试结果为:
可见,ReentrantLock重入锁是独占的,线程只能一个一个获取释放。