多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
[toc] 提几个问题: - synchronized保证原子性,volatile保证可见性; - 不用volatile,只用synchronized修饰,能保证可见性吗? ## 队列同步器AQS 队列同步器AbstractQueuedSynchronizer(以下简称同步器),是用来构建锁或者其他同步组件的基础框架。 使用同步器提供的3个方法(getState()、setState(int newState)和compareAndSetState(int expect,int update))来进行操作,因为它们能够保证状态的改变是安全的。 ### 同步器实现原理 同步器依赖内部的同步队列(一个FIFO双向队列)来完成同步状态的管理,当前线程获取同步状态失败时,同步器会将`当前线程`以及`等待状态`等信息构造成为一个`节点(Node)`并将其加入同步队列,同时会阻塞当前线程;当同步状态释放时,会把首节点中的线程唤醒,使其再次尝试获取同步状态。 `设置尾结点`:通过CAS实现。 `设置头结点`:设置首节点是通过获取同步状态成功的线程来完成的,由于只有一个线程能够成功获取到同步状态,因此设置头节点的方法并不需要使用CAS来保证,它只需要将首节点设置成为原首节点的后继节点并断开原首节点的next引用即可。 ### 独占式同步状态获取流程 ![](https://img.kancloud.cn/3a/40/3a402a050e9412968653c0e31e2bd325_638x684.png) 1. 在**获取同步状态**时,同步器维护一个同步队列,获取状态失败的线程都会被加入到队列中并在队列中进行自旋; 2. **移出队列**(或停止自旋)的条件是前驱节点为头节点且成功获取了同步状态。 3. 在**释放同步状态**时,同步器调用tryRelease(int arg)方法释放同步状态,然后唤醒头节点的后继节点。 ## 悲观锁 ### synchronized - 锁功能的实现:synchronized是通过监视器实现锁功能的。随着jdk版本的升级,synchronized性能不断提升,分为偏向锁、轻量锁、重量锁等。 - 线程唤醒:不能唤醒指定线程。 阻塞方法:wait() ### ReentrantLock - ReentrantLock是对象锁,使用时需要`new ReentrantLock()`,线程独享,可以唤醒指定线程。 - 阻塞方法:需要用到Condition对象,调用`condition.wait()`方法。 > ReentrantLock是基于CAS实现的悲观锁,从宏观上讲它是悲观锁,从微观上讲,它是基于乐观锁实现的。 ## 乐观锁CAS - 无线程切换 - 阻塞方法:LockSupport.park() - 解锁方法:LockSupport.unpark(线程名称) #### Condition对象 每个Condition对象都包含一个队列——**等待队列**,该队列是实现`等待/通知`功能的关键。 ![](https://img.kancloud.cn/86/d7/86d7f2edaa1efc73f988598c71b0718a_1171x369.png) Condition对象拥有等待队列首尾对象的引用。 ### LockSupport