Java并发 aqs
AQS:AbstractQueuedSynchronizer
一、AQS是一个用来构建锁和同步器的框架,使用AQS能简单且高效地构造出应用广泛的大量的同步器。
二、原理:AQS核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH队列锁实现的,即将暂时获取不到锁的线程加入到队列中。
原理图:
三、学习路线图。大量的应用在j.u.c下的各个基础类和工具栏,构成Java并发包的基础。
四、1、有一个重要的状态标志——state,该属性是一个int值,表示对象的当前状态。三个protected final的方法来改变state的值,分别是:getState、setState(int)、compareAndSetState(int, int)。
private volatile int state; /** * Returns the current value of synchronization state. * This operation has memory semantics of a {@code volatile} read. * @return current state value */ protected final int getState() { return state; } /** * Sets the value of synchronization state. * This operation has memory semantics of a {@code volatile} write. * @param newState the new state value */ protected final void setState(int newState) { state = newState; }
2、AQS定义两种资源共享方式
-
Exclusive(独占):只有一个线程能执行,如ReentrantLock。又可分为公平锁和非公平锁:
- 公平锁:按照线程在队列中的排队顺序,先到者先拿到锁
- 非公平锁:当线程要获取锁时,无视队列顺序直接去抢锁,谁抢到就是谁的
- Share(共享):多个线程可同时执行,如Semaphore/CountDownLatch。Semaphore、CountDownLatCh、 CyclicBarrier、ReadWriteLock 。
// exclusive mode protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException(); } protected boolean tryRelease(int arg) { throw new UnsupportedOperationException(); } // shared mode共享模式 protected int tryAcquireShared(int arg) { throw new UnsupportedOperationException(); } protected boolean tryReleaseShared(int arg) { throw new UnsupportedOperationException(); }
3、用到了模板设计模式
五、同步工具类
CountDownLatch
倒数计时。是一个同步工具类,用来协调多个线程之间的同步。这个工具通常用来控制线程等待,它可以让某一个线程等待直到倒计时结束,再开始执行。
public class CountDownLatchDemo implements Runnable { static final CountDownLatch latch = new CountDownLatch(10); static final CountDownLatchDemo demo = new CountDownLatchDemo(); @Override public void run() { // 模拟检查任务 try { Thread.sleep(new Random().nextInt(20) * 100); System.out.println("check complete"); } catch (InterruptedException e) { e.printStackTrace(); } finally { // 计数减一 // 放在finally避免任务执行过程出现异常,导致countDown()不能被执行 latch.countDown(); } } public static void main(String[] args) throws InterruptedException { ExecutorService exec = Executors.newFixedThreadPool(10); for (int i = 0; i < 10; i++) { exec.submit(demo); } // 等待检查 latch.await(); // 发射火箭 System.out.println("Fire!"); // 关闭线程池 exec.shutdown(); } }
Semaphore
synchronized 和 ReentrantLock 都是一次只允许一个线程访问某个资源,Semaphore(信号量)可以指定多个线程同时访问某个资源。
不错的博文:https://blog.csdn.net/lxltmac/article/details/84871929