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.并发的风险 竞争-----多个线程对内存数据数据进行读写操作时,对数据处理结果的一个 ...
随机推荐
- html5 web 摇一摇切换歌曲
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...
- Winpython环境下mayavi配置
Winpython环境下mayavi配置 在pythonxy中会直接有mayavi软件包,但是所附带的杂包实在太多.本人一直用的是window下的winpython或者linux下的anaconda来 ...
- 2018.06.30 BZOJ 2342: [Shoi2011]双倍回文(manacher)
2342: [Shoi2011]双倍回文 Time Limit: 10 Sec Memory Limit: 128 MB Description Input 输入分为两行,第一行为一个整数,表示字符串 ...
- SessionCacheTest03.testLoad Unrooted Tests initializationError
这个错误主要是没有加载@Test这个标签,就是把其转化为一个juit测试的类.增加之后就没有问题了,当然还有很多人说是自己的Juit的版本问题,那就改下版本,还有说是没有加载两个类包,为了完整我就把包 ...
- 20145209 2016-2017-2 《Java程序设计》第6周学习总结
20145209 2016-2017-2 <Java程序设计>第6周学习总结 教材学习内容总结 4.1 Y86指令集体系结构 •有8个程序寄存器:%eax.%ecx.%edx.%ebx.% ...
- hdu1089 Ignatius's puzzle
题目 其实这道题不是很难,但是我刚开始拿到这道题的时候不知道怎么做, 因为这个式子我就不知道是干什么的: 65|f(x) 百度解释(若a/b=x...0 称a能被b整除,b能整除a,即b|a,读作& ...
- D3_book 11.1 pie
<!-- pie example --> <!DOCTYPE html> <meta charset="utf-8"> <style> ...
- 移动端与PC端的viewport
第一种解析: 设备像素,就是我们直觉上觉得"靠谱"的像素,这些像素为所使用的各种设备提供了正规的分辨率,并且其值可以通过(通常情况下)从screen.width/height属性中 ...
- [翻译] FastReport "Text" 对象中使用表达式
文本对象的最重要的功能之一是它不仅能够显示静态文本还能显示表达式.表达式混合在正常的文本内容中,让我们看一个简单的例子,他是如何工作的.在文件对象的内容中,输入以下字符: Hello, World! ...
- Android ListView setOnItemClickListener/setOnItemSelectedListener,无效
在Android 开发中,有时候我们在设置,LIstview,GridView,这些View的时候,再给他们设置:setOnItemClickListener/setOnItemSelectedLis ...