🚀 优质资源分享 🚀
学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
🧡 Python实战微信订餐小程序 🧡 | 进阶级 | 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。 |
💛Python量化交易实战💛 | 入门级 | 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 |
笔记主要参考《Java并发编程的艺术》并且基于JDK1.8的源码进行的刨析,此篇只分析独占模式,后续在ReentrantReadWriteLock和 CountDownLatch中 会重点分析AQS的共享模式
一丶Lock
锁是用来控制多个线程访问共享资源的方式,一般来说,一个锁可以防止多个线程同时访问共享资源(这种锁称为独占锁,排他锁)但是有些锁可以允许多个线程并发访问共享资源,比如读写锁
1.Lock接口的方法:
方法 | 作用 |
---|---|
void lock() | 获取锁,调用该方法的线程将会获取锁,当锁获得之后从该方法返回 |
void lockInterruptibly() | 可中断地获取锁,该方法会响应中断,在锁的获取可以中断当前线程,如果在获取锁之前设置了中断标志,or获取锁的中途被中断or其他线程中断该线程则抛出InterruptedException并清除当前线程的中断状 |
boolean tryLock() | 尝试非阻塞的获取锁,调用方法会立即返回,如果可以获取到锁返回true |
boolean tryLock(long time, TimeUnit unit) throws InterruptedException | 超时获取锁,从当前返回有三种情况1.超时时间内获取到锁2.当前线程在超时时间内被中断3.超时间结束没有获取到锁,返回false |
void unLock | 释放锁 |
Condition newCondition() | 获取等待通知的组件,该组件和当前锁绑定,只有获取到锁调用wait方法后当前线程将放弃锁,后续被其他线程signal继续争抢锁 |
2.Lock相比synchronized具备的特性
- 尝试非阻塞的获取锁
- 响应中断的获取锁
- 超时获取锁
synchronized相比于Lock 更加简单,更不容易犯错,但是不够灵活
3.使用Lock的经典范式
获取锁的过程不要写在try中,避免获取锁失败最后finally释放其他线程持有的锁
二丶AbstractQueuedSynchronizer队列同步器
使用一个int成员变量state表示同步状态,内置的FIFO队列来完成资源的获取和线程的排队工作,支持独占也支持共享的获取同步状态。
三个变量被volatile修饰,保证其线程可见性
1.队列同步器可以被重写的方法
方法 | 说明 |
---|---|
protected boolean tryAcquire(int arg) | 独占的获取锁,需要查询当前状态并判断同步状态是否符合预期,然后再进行CAS改变同步状态 |
protected boolean tryRelease(int arg) | 独占式释放同步状态,等待获取同步状态的线程将有机会获取同步状态 |
protected int tryAcquireShared(int arg) | 共享式的获取同步状态,放回大于等于0()的值表示成功,反之失败 |
protected boolean tryReleaseShared(int arg) | 共享式释放同步状态 |
protected boolean isHeldExclusively() | 当前队列同步器释放再独占模式下被线程占用,一般表示当前线程是否独占 |
2.队列同步器提供的模板方法
方法 | 说明 |
---|---|
void acquire(int arg) | 独占式获取同步状态,如果获取成功那么直接返回,反之进入同步队列中等待, |
void acquireInterruptibly(int arg) | 和acquire,但是此方法支持在获取锁的过程中响应中断,如果当前线程被中断那么抛出InterruptedException |
boolean tryAcquireNanos(int arg, long nanosTimeout) | 在acquireInterruptibly的基础上增加了超时限制,如果在指定时间内没有获取到同步状态那么返回false反之true |
void acquireShared(int arg) | 共享式获取同步状态,如果没有获取到那么进入等待队列等待,和acquire不同的式支持同一个时刻多个线程获取 |