JAVA并发编程学习笔记------多线程调优
1. 多线程场景下尽量使用并发容器代替同步容器
(如ConcurrentHashMap代替同步且基于散列的Map, 遍历操作为主要操作的情况下用CopyOnWriteArrayList代替同步的List)
ConcurrentHashMap:分段锁机制,多线程条件下优于HashMap+synchronized的组合方式;
CopyOnWriteArrayList: 每次修改时都会创建并重新发布一个新的容器副本,从而实现可变性。容器的迭代器保留一个指向底层基础数组的引用,这个数组当前位于迭代器的起始位置,由于他不会被修改,
所以在对其进行同步时只需确保数组内容的可见性。
2. 避免死锁
a)尽量不要在释放锁之前竞争其他锁:一般可以通过细化同步方法来实现,只在真正需要保护共享资源的地方去拿锁,并尽快释放锁,这样可以有效降低在同步方法里调用其他同步方法 的情况
b)顺序索取锁资源: 如果实在无法避免嵌套索取锁资源,则需要制定一个索取锁资源的策略,先规划好有哪些锁,然后各个线程按照一个顺序去索取
c)尝试定时锁: Java 5提供了更灵活的锁工具,可以显式地索取和释放锁。那么在索取锁的时候可以设定一个超时时间,如果超过这个时间还没索取到锁,则不会继续堵塞而是放弃此次任务,如下:
public boolean trySendOnSharedLine(String message, long timeout, TimeUnit unit) throws InterruptedException {
long nanosToLock = unit.toNanos(timeout) - estimatedNanosToSend(message);
if (!lock.tryLock(nanosToLock, NANOSECONDS)){
return false;
}
try {
return sendOnSharedLine(message);
} finally {
lock.unlock();
}
}
这样可以效打破死锁条件。
3. Amdahl定理:
speedup<= 1/(F+(1-F)/N)
其中,F是串行化比例,N是处理器数量,由上可知,只有尽可能减少串行化,才能最大化地提高可扩展能力。降低串行化的关键就是降低锁竞争,当很多并行任务挂在锁的获取上,就是串行化的表现.
4. 降低锁竞争
1)缩小锁的范围
尽量缩小锁保护的范围,快进快出,因此尽量不要直接在方法上使用synchronized关键字,而只是在真正需要线程安全保护的地方使用
2)减小锁的粒度
尽量避免大段的synchronize代码块
3)减少共享资源的依赖
在多线程开发中尽量减少对共享资源的依赖,比如对象池的技术应该慎重考虑,新的JVM对新建对象以做了足够的优化,性能非常好,如果用对象池不但不能提高多少性能,反而 会因为锁竞争导致降低线程的可并发性。
4)使用读写分离锁来替换独占锁
Java 5提供了一个读写分离锁(ReadWriteLock)来实现读-读并发,读-写串行,写-写串行的特性。这种方式更进一步提高了可并发性,因为有些场景大部分是读操作,因此没必要串行工作。
5. 切换上下文
线程比较多的时候,操作系统切换线程上下文的性能消耗是不能忽略的,
6. 内存同步
当使用到synchronized、volatile或Lock的时候,都会为了保证可见性导致更多的内存同步,这就无法享受到JMM结构带来了性能优化。
7. 适当使用同步工具类
(1) 闭锁(CountDownLatch): 延迟线程的进度直到其达到终止状态,用来确保某些活动直到其他活动都完成后才继续执行;一次性对象,一旦进入终止状态,就不能被重置;
(2) FutureTask: 可生成结果的Callable,如果有结果可用,那么FutureTask.get将立即返回结果,否则它会一直阻塞,直到结果计算出来再将其返回。
(3) 信号量(Semaphore):用来控制同时访问某个特定资源的操作数量,或者同时某个指定操作的数量,Semaphore还可以用来实现某种资源池,或者对容器施加边界。
(4) 栅栏(Barrier): 类似于闭锁,区别在于所有线程必须同时到达栅栏位置才能继续执行,闭锁用于等待事件,而栅栏用于等待其他线程。可被重置用于下次使用。两种实现方式:CyclicBarrier,Exchanger
8. 实际情况中,应尽可能的使用现有的线程安全对象(例如AtomicInteger)来管理类的状态
9. 在多线程程序中使用共享且可变的long和double等类型的变量也是不安全的,除非用volatile来声明它们,或者用锁保护起来。
JAVA并发编程学习笔记------多线程调优的更多相关文章
- Java并发编程学习笔记
Java编程思想,并发编程学习笔记. 一.基本的线程机制 1.定义任务:Runnable接口 线程可以驱动任务,因此需要一种描述任务的方式,这可以由Runnable接口来提供.要想定义任务,只需实现R ...
- Java并发编程学习笔记 深入理解volatile关键字的作用
引言:以前只是看过介绍volatile的文章,对其的理解也只是停留在理论的层面上,由于最近在项目当中用到了关于并发方面的技术,所以下定决心深入研究一下java并发方面的知识.网上关于volatile的 ...
- Java 并发编程学习笔记 理解CLH队列锁算法
CLH算法实现 CLH队列中的结点QNode中含有一个locked字段,该字段若为true表示该线程需要获取锁,且不释放锁,为false表示线程释放了锁.结点之间是通过隐形的链表相连,之所以叫隐形的链 ...
- Java并发编程学习笔记(一)——线程安全性
主要概念:线程安全性.原子性.原子变量.原子操作.竟态条件.复合操作.加锁机制.重入.活跃性与性能. 1.当多个线程访问某个状态变量并且其中有一个线程执行写入操作时,必须采用同步机制来协同这些线程对变 ...
- JAVA并发编程学习笔记------对象的可见性及发布逸出
一.非原子的64位操作: 当线程在没有同步的情况下读取变量时,可能会得到一个失效值,但至少这个值是由之前某个线程设置的值,而不是一个随机值,这种安全性保证被称为最低安全性.最低安全性适用于绝大多数变量 ...
- [转]JAVA并发编程学习笔记之Unsafe类
1.通过Unsafe类可以分配内存,可以释放内存:类中提供的3个本地方法allocateMemory.reallocateMemory.freeMemory分别用于分配内存,扩充内存和释放内存,与C语 ...
- Java并发编程学习笔记(三)——对象的组合
重要概念: 1.在设计线程安全类的过程中,需要包含以下三个基本要素: (1)找出构成对象状态的所有变量. (2)找出约束状态变量的不变性条件. (3)建立对象状态的并发访问管理策略. 2.
- Java并发编程学习笔记(二)——对象的共享
主要概念:可见性.重排序.失效数据.最低安全性.发布.逸出.线程封闭(Ad-hoc.栈封闭.ThreadLocal类).不变性.Final域.事实不可变对象. 1.在没有同步的情况下,编译器.处理器以 ...
- java并发编程学习笔记(一)初识并发原子性
1.并发的意义 现在是一个多核的时代,并发的存在意义就是为了能够充分利用多核计算机的优势,提高程序的运行效率: 2.并发的风险 竞争-----多个线程对内存数据数据进行读写操作时,对数据处理结果的一个 ...
随机推荐
- 用Fiddler抓到的报文Content-Type: application/x-www-form-urlencoded,怎样解析?
抓到的HTTPS请求报文,在报文头中Content-Type: application/x-www-form-urlencoded 报文体为: entrypoint=clientmanagement& ...
- jqgrid单元格合并
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx. ...
- part1:6-Linux文本编辑器vi
vi编辑器简介: vi是Linux系统的第一个全屏幕交互式编辑器:vim则是vi的升级版得到广大用户青睐. vim有三种工作模式:命令行模式.插入模式.底行模式 命令行模式常用功能键: yy:复制当前 ...
- 使用delphi 开发多层应用(二十二)使用kbmMW 的认证管理器
从kbmmw 4.4 开始,增加了认证管理器,这个比原来的简单认证提供了更多的功能.细化了很多权限操作. 今天对这一块做个介绍. 要做一个认证管理,大概分为以下5步: 1. 定义你要保护的资源,一般 ...
- mysql数据库中如何查询日期在两个时间之间的关系
select * from banner where addDate between '2017-06-04' and '2017-06-06';
- 2018.07.17 牛奶模式Milk Patterns(二分+hash)
传送门 一道简单的字符串.这里收集了几种经典做法: SAM,不想写. 后缀数组+二分,不想写 后缀数组+单调队列,不想写 hash+二分,for循哈希,天下无敌!于是妥妥的hash 代码如下: #in ...
- python 求第k个最大数
#coding = utf-8 import sys def Cal_NO(a,b): nums=sorted(a,reverse=True) result=nums[b-1] return resu ...
- php读取用友u8客户档案
include('../common/conn.php'); $list=[]; $sql="SELECT a.cCusCode,a.cCusName,b.cCCName,a.cCusDep ...
- 城市边界线预测(根据灯光指数)(PUL)
1.EXEALL.m function EXEALL(FilePath, FileName)%执行所有流程% FilePath: 文件夹所在路径% FileName: 文件夹名称 FullPath = ...
- SPATIALINDEX_LIBRARY Cmake
https://libspatialindex.org/ QGIS:https://github.com/qgis/QGIS/blob/master/cmake/FindSpatialindex.cm ...