当前位置: 首页 > >

java aqs_Java

发布时间:

最*真的是对Java中的基础思想狠下功夫,因为面试一线大厂,这种基础简直是必问。上一节讲过CAS,这回我们来看AQS。


1、学*思路:从非公*锁进入源码,可以看到Sync extends AbstractQueuedSynchronizer,这个AbstractQueuedSynchronizer就是AQS。


2、有CAS还不够吗,为什么设计AQS?


CAS 只是保证原子性。而AQS却能保证并发线程的有序且安全。


Java作者是想把AQS做成并发编程的基础组件。显示锁、读写锁的源码中都有AQS,线程池中的Worker也使用了AQS。所以记住:AQS是并发编程中很基础很基础的组件。


3、理解AQS前,先了解下LockSupport和CLH队列锁


(1)LockSupport:提供了线程的阻塞和唤醒功能。是构建AQS组件的基础工具。


(2)CLH队列锁:一种思想。尝试获取锁的多个线程,当一个线程获取到锁,那么其他的线程要等待,这些等待的线程会被放入一个列表,如图所示:



每一个线程都会被包装成这样的一个节点:前驱节点的引用和当前节点的lock状态。


新来的线程会放到队列/链表尾部,新线程将自己包装成一个节点,节点中包含自身锁的状态和前驱节点的引用,而且线程节点一直在这个前驱节点的引用上一直自旋(监控),看前驱节点的lock状态是否改变,前驱借钱锁释放了,就会locked变为false。后面的节点监测到这个就会改状态。


4、真正了解AQS


AQS 是面向锁的开发者的,像我们*时要用到锁时直接使用Lock就好了,不会去再实现AQS。也就是说AQS时锁的源码中的思想,太底层了。


AQS是抽象类,里面几个方法没有实现,这是用了模板方法模式,这些实现放到子类中去实现。


对于锁,它是有状态的,必须有一个标志位来标志,而AQS中是使用了一个volatile int state表示,volatile保证线程间的可见性,所以其他等待的线程可以见到这个锁标志,AQS又用CAS通过对这个标志状态 由0 变1来完成锁获取锁释放的变化,保证了state的线程安全。这个标志叫state,非常重要的变量。


5、总结


AQS的数据结构:链表 + 状态标志


AQS = CLH队列锁 + CAS:


CLH队列锁:阻塞线程排队


CAS:保证锁的线程安全



友情链接: