Java锁---一图秒懂
2024-06-27 14:05:06 0 举报
AI智能生成
该图片简要概括了Java中的锁机制。在Java中,锁主要用于控制对共享资源的并发访问,从而确保数据的完整性和一致性。根据锁的实现方式和适用场景,可以分为内部锁(如synchronized关键字)和显式锁(如ReentrantLock类)。内部锁是Java内置的锁机制,可以在方法或代码块上使用synchronized关键字实现。显式锁则是Java并发包中提供的锁API,如ReentrantLock、ReentrantReadWriteLock等,它们提供了更加强大的功能和灵活性。在使用锁时,需要注意死锁和饥饿问题,并通过合适的锁机制和策略来避免这些问题。
作者其他创作
大纲/内容
锁的分类
公平与否
公平锁
定义:竞争锁时先判断同步队列里是否有其他线程在等待,若有则要到队尾进行排队
公平锁代表
ReentrantLock
ReentrantReadWriteLock
非公平锁
定义:竞争锁时先尝试获取锁,失败后才会插入同步队列尾部
非公平锁代表
ReentrantLock
ReentrantReadWriteLock
synchronized
独占与否
独占锁
定义:锁同时只能被一个线程占有(也叫互斥锁)
独占锁代表
ReentrantLock
synchronized
ReentrantReadWriteLock中的writeLock
共享锁
定义:锁可以被多个线程共享
共享锁代表
ReentrantReadWriteLock中的readLock
悲观与乐观
乐观锁
定义:线程操作临界区数据前不会上锁,只有真正修改数据时才会比对数据是否
已经被其他线程修改过;
乐观是中思想,技术基础是:CAS
已经被其他线程修改过;
乐观是中思想,技术基础是:CAS
乐观锁代表
自旋锁
自适应自旋锁
无限次自旋锁
悲观锁
定义:线程操作临界区数据前总是悲观地认为会有别的线程操作改数据,
因此每次都先去获取锁,成功后再操作数据
因此每次都先去获取锁,成功后再操作数据
悲观锁代表
ReentrantLock
ReentrantReadWriteLock
synchronized
重入与否
可重入锁
定义:线程获取了A锁,在没有释放A锁之前,还能继续获取A锁,那么说明A锁是可重入的
可重入锁代表
ReentrantLock
ReentrantReadWriteLock
synchronized
非可重入锁
未实现非可重入锁
阻塞与否
阻塞锁
定义:线程获取锁失败后会阻塞自身
阻塞锁代表
ReentrantLock
ReentrantReadWriteLock
synchronized
自旋锁
定义:无需阻塞
自旋锁代表
自适应自旋锁
无限次自旋锁
按照作用对象区分
只有synchronized才会有类锁、对象锁概念
只有synchronized才会有类锁、对象锁概念
对象锁
定义:锁与对象实例关联
对象锁代表
synchronized
类锁
定义:锁与类对象(class)关联
类锁代表
synchronized
可中断与否
可中断锁
定义:线程在获取锁的过程中可响应中断(抛出中断异常),推出
可中断锁代表
ReentrantLock
ReentrantReadWriteLock
不可中断锁
定义:线程在获取锁的过程中不响应中断
不可中断锁代表
synchronized
能否限时等待
可限时等待锁
定义:一定时间后,若还是不能获取锁,退出获取锁流程
可限时等待锁代表
ReentrantLock
ReentrantReadWriteLock
非限时等待锁
定义:线程获取锁失败,阻塞直到获取锁为止(除非响应中断)
非限时等待锁代表
synchronized
锁的实现方式
JVM实现
synchronized
关联每个对象
作用域:方法与代码块
作用对象:类与对象
类对象
实例对象
不同阶段状态锁
无锁
定义:没有线程关联锁
偏向锁
定义:线程锁住的是MarkWord
锁只被一个线程访问,对象头里(MarkWord字段)记录着当前线程ID。
当该线程再次获取锁时,仅仅只需要比对MarkWord里的线程ID是否是自己的,
若是直接获取锁,否则可能会升级为轻量级锁
锁只被一个线程访问,对象头里(MarkWord字段)记录着当前线程ID。
当该线程再次获取锁时,仅仅只需要比对MarkWord里的线程ID是否是自己的,
若是直接获取锁,否则可能会升级为轻量级锁
适用场景:锁只被一个线程访问的场景
轻量级锁
定义:线程锁住的是MarkWord
线程访问该锁时,在无锁状态,仅仅只需要一次CAS修改MarkWord里面的指针
指向线程自身LockRecord,成功则获取锁,否则可能会升级为重量级锁
线程访问该锁时,在无锁状态,仅仅只需要一次CAS修改MarkWord里面的指针
指向线程自身LockRecord,成功则获取锁,否则可能会升级为重量级锁
适用场景:锁被多个线程交替访问的场景
重量级锁
定义:线程锁住的是ObjectMonitor对象
线程修改ObjectMonitor对象成功,则获取了锁,失败则阻塞等待
线程修改ObjectMonitor对象成功,则获取了锁,失败则阻塞等待
适用场景:多个线程并发访问
实现的功能
非公平锁
独占锁
悲观锁
可重入锁
阻塞锁
非限时等待锁
不可中断锁
维护同步队列
维护等待队列
与等待/通知机制有关
JUC实现
AQS
基本概念
定义:全称AbstractQueueSynchronizer,
是JUC下的同步器基础框架
是JUC下的同步器基础框架
升级版:AbstractQueueLongSynchronizer
实现基本功能
共享/独占模式
可中断/不可中断
可限时等待/非限时等待
维护同步队列
维护等待队列
与等待/通知机制有关
基于AQS的锁
ReentrantLock
实现功能
继承自AQS基本功能
独占模式
公平/非公平
可重入
基于此封装的同步器
CyclicBarrier
ReentrantReadWriteLock
实现功能
继承自AQS基本功能
读锁是共享模式
写锁是独占模式
公平/非公平
可重入
读写锁关系
写写互斥
读读共享
读写互斥
特殊情况:允许同一线程先写,在释放写锁之前,
同一线程再读(写锁降级)
同一线程再读(写锁降级)
基于AQS的同步器
Semaphore
基于AQS共享模式
CountDownLatch
基于AQS共享模式
ThreadPoolExecutor.Worker
基于AQS独占模式
锁的核心
基本数据结构
共享的锁变量
volatile
保证可见性、顺序性
CAS
底层CPU原子性修改变量值
同一时刻,只能有一个线程成功修改变量
同步/等待队列
同步队列
获取锁失败后加入同步队列
等待队列
因某个条件不满足进入等待队列等待
操作数据结构
获取锁
修改锁变量
释放锁
修改锁变量
线程挂起与唤醒
AQS使用LockSupport
UnSafe
Parker
synchronized
ParkEvent
配合等待/通知机制
配合synchronized
线程因某个条件阻塞等待
调用Object.wait
线程被其他线程唤醒
调用Object.notify/notifyAll
配合AQS
线程因某个条件阻塞等待
调用AQS
Condition.await
线程被 其他线程唤醒
调用AQS
Condition.signal/signalAll
通过配合ReentrantLock/ReentrantReadWriteLock使用Condition
同一个锁能关联多个条件/等待
内部逻辑
等待
线程被加入到等待队列尾部
线程释放当前持有的锁
线程挂起
被唤醒后继续竞争锁
成功
从同步队列里移除
失败
继续挂起
通知
线程被从等待队列移动到同步队列里
当其他线程释放锁后,会唤醒同步队列里的线程
收藏
0 条评论
下一页