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

https://segmentfault.com/a/1190000016885682

posted @ 2019-08-10 09:49  阿罗luo  阅读(187)  评论(0编辑  收藏  举报