并发控制——锁机制的优化
来源:互联网 发布:数据挖掘 十大算法代码 编辑:程序博客网 时间:2024/06/05 14:12
问题背景:
锁的开销:多线程使系统除处理功能需求外,另有维护多线程的额外开销,包括:
1. 线程本身的元数据
2. 线程调度
3. 线程上下文切换
死锁:线程间相互等待又不释放自身资源,形成循环等待
锁的优化方法:
我们需要通过合理的手段,降低锁竞争、锁冲突,以提高并发能力
代码层面:
1. 减少锁持有时间:只在必要的代码篇幅上加锁,比较容易注意到的降低锁竞争的方法。
2. 锁粗化:与上条相对。由于锁不断请求、同步、释放也很耗资源,某些情况下我们需要对锁进行适当的粗化。如:
a. 将锁置于循环外
b. 快速执行的功能点不需要进行锁分离
3. 减少锁粒度:通过分割数据结构,缩小锁定对象范围,拆分锁实现锁分离,如:ConcurrentHashMap中将HashMap拆分成多个Segement分段锁
缺点:系统需要获得全局锁时耗费资源较多。
4. 锁分离:通过对系统不同功能点(不同操作)的分割进行锁分离
4.1 读写锁换独占锁:读操作不会影响数据的完整性和一致性,应允许多线程并行。读锁相容,写锁独占。写锁未释放的,无法往对象上加任何锁,如:CopyOnWriteList适合读多写少的场景
4.2 重入锁与内部锁:
a.重入锁:利用ReentrantLock和Condition结合,对独占锁进行分离。重入锁提供锁等待、锁中断、快速轮训、有助于避免死锁,如LinkedBlockingQueue
b.内部锁:用synchronized结合Object.wait()及Object.notify()实现。使用简单,JVM内部有优化。
c.在可正常实现系统功能情况下,推荐使用内部锁
JVM层面:
1. 自旋锁: 防止锁等待小段CPU时,做线程切换,进行频繁的挂起、恢复,提升线程执行的连贯性。用于锁竞争不激烈,锁占用时间段的并发场景
-XX:+UseSpirinning 开启自旋锁
-XX:+PreBlockSpin 设置等待次数
2. 锁消除: JVM编译时,进行上下文扫描,进行逃逸分析,消除不存在资源竞争的锁,如:方法中局部变量(线程私有,不会逃逸出栈帧)为JDK内置线程安全的数据结构(如StringBuffer),可消除该数据结构中带有的加锁操作
-XX:+DoEscapeAnalysis 开启逃逸分析
-XX:+EliminateLock 开启锁消除
3. 锁偏向: 在锁竞争激烈的场合,应该禁用
-XX:-UseBiaseLocking 关闭锁偏向
CAS:
无锁机制保证数据的一致性,基于比较并交换(CompareAndSwap),一种非阻塞同步的方法,是乐观锁的一种实现。
优点:消除锁竞争,没有相互等待,对死锁问题免疫。TheadLocal、java.util.concurrent.atomic中的原子类是基于此实现的。
缺点:将冲突交由应用层实现,增加了开发难度。不过现在有现成的无锁并行框架,如Apache的Amino框架。
共享数据的并发访问控制方法
volatile 保证变量可见性
Semaphore 信号量。实现对象池
ThreadLock 线程局部变量。生成副本、无锁机制
- 并发控制——锁机制的优化
- Hibernate的乐观锁并发控制机制
- 乐观机制的并发控制
- hbase的并发控制机制
- 数据库并发控制及SQL Server的并发控制机制
- SQLite3的锁机制和并发控制详解
- informix的事务、并发控制、锁机制、隔离级别
- 数据库并发事务控制四:postgresql数据库的锁机制
- Informix的事务、并发控制、锁机制、隔离级别
- Informix的事务、并发控制、锁机制、隔离级别
- Hibernate的悲观锁并发控制机制及LockMode
- 多线程并发 synchronized对象锁的控制与优化
- 多线程并发 synchronized对象锁的控制与优化
- MySQL优化系列(八)--锁机制超详细解析(锁分类、事务并发、引擎并发控制)
- MySQL优化系列(八)--锁机制超详细解析(锁分类、事务并发、引擎并发控制)
- 并发控制——“锁”
- Java并发的核心控制机制
- 事务并发控制和锁机制
- hello word
- 1
- 2
- plsql常用函数汇总
- 音视频数据处理(18)--- H.264的NAL层数据单元NALU与I帧判断
- 并发控制——锁机制的优化
- JAVA技术的提升备注
- 数据库设计工具的使用(实用)
- nihao
- MT2503与SIM系列模块连接服务器区别比较
- IntelliJ IDEA的初次使用(二)
- linux安装JDK
- maven:Fatal error compiling: 无效的目标 发行版: 1.8 -> [Help 1]
- 为什么从java源码到class字节码是由编译器完成