并发编程 AQS

154 阅读2分钟

我听过一句很有道理的一句话,重要的不是学会什么,重要的是学会学习的方式,这句话在java的学习中很精辟,现在的编程学习途径有很多,就拿并发编程学习的资料来说,网上一抓一大把,视频呀,学习班呀太多太多了,那在这个时候,就要选择自己最适合的方式,以前我说,喜欢姑娘的思想是,物有百味,适口者珍,学习也是一样的,不多说了,下面就说说AQS

AQS是啥,之前的文章我说过,其实他是一个抽象类的缩写,

AbstractQueuedSynchronizer 1 他的实现类有哪些

ReentrantLock、Semaphore、CountDownLatch、CyclicBarrier

继续说说他们是怎么实现的

Semaphore 这个是信号量锁

public Semaphore(int permits) { sync = new NonfairSync(permits); } 创建他的时候,实际上是委托sync类来执行方法

abstract static class Sync extends AbstractQueuedSynchronizer 而sync类 继承了AQS所以说,Semaphore 是AQS实现类的一种

那Semaphore是干啥的呢

信号量锁像连接池 让几个先执行 然后其他几个等待这几个执行完

public static void main(String[] args) {
    // 线程池
    ExecutorService exec = Executors.newCachedThreadPool();
    //设置信号量同时执行的线程数是5
    final Semaphore semp = new Semaphore(2);
    // 模拟20个客户端访问
    for (int index = 0; index < 8; index++) {
        final int NO = index;
        exec.execute(() -> {
            try {
                //使用acquire()获取锁
                semp.acquire();
                System.out.println("Accessing: " + NO);
                //睡眠1秒
                Thread.sleep(2000);
            } catch (InterruptedException ignore) {
            }  finally {
                //使用完成释放锁
                semp.release();
            }
        });
    }
    // 退出线程池
    exec.shutdown();
}

CountDownLatch 这是一个门栓的思想,就是要等到船员齐了再一起上传

    CountDownLatch latch = new CountDownLatch(10);
    ExecutorService exec = Executors.newFixedThreadPool(10);
    for (int i = 0; i < 10; i++) {
        exec.execute(() -> {
            try {
                int millis = new Random().nextInt(10000);
                System.out.println("等待游客上船,耗时:" + millis + "(millis)");
                Thread.sleep(millis);
            } catch (Exception ignore) {
            } finally {
                latch.countDown(); // 完事一个扣减一个名额
            }
        });
    }
    // 等待检查
    latch.await();
    System.out.println("船长急躁了,开船!");
    // 关闭线程池
    exec.shutdown();
}

2 实现AQS的锁有那些

自旋锁、互斥锁、读锁写锁、条件产量、信号量、栅栏都是AQS的衍生物

栅栏是啥? 内存屏障,几乎所有的处理器至少支持一种粗粒度的屏障指令,通常被称为“栅栏(Fence)”