《java并发编程实战》读书笔记8--死锁,性能与可伸缩性,锁粒度锁分解锁分段
第10章 避免活跃性危险
10.1 死锁
-10.1.1 锁顺序死锁
最简单的一种死锁形式:
-10.1.2 动态的锁顺序死锁
可以通过下面的方法来解决:
-10.1.3 在协作对象之间发生死锁
-10.1.4 开放调用
如果在调用某个方法时不需要持有锁,那么这种调用就被称为开放调用。
-10.1.5 资源死锁
当多个线程在相同资源上等待时,也会发生死锁。
10.2 死锁的避免与诊断
-10.2.1 支持定时的锁
显示使用Lock类中的定时tryLock功能(见13章)来代替内置锁机制。
-10.2 通过线程转储信息来分析死锁
10.3 其他活跃性危险
-10.3.1 饥饿
当线程由于无法访问它所需要的资源而不能继续执行时,就发生了"饥饿"。引发饥饿最常见的资源就是CPU时钟周期。
-10.3.2 糟糕的响应性
-10.3.3 活锁
这种问题虽然不会阻塞线程,但也不能继续执行,因为线程将不断重复执行相同操作,而且总会失败。活锁通常发生在处理事务消息的应用程序中:如果不能成功处理某个消息,那么消息处理机制将回滚整个事务,并将它重新放到队列的开头。如果消息处理器在处理某种特定类型的消息时存在错误并导致它失败,那么每当这个消息从队列中取出并传递到存在错误的处理器时,都会发生事务回滚。由于这条消息又被放到队列开头,因此处理器将被反复调用,并返回相同结果。虽然处理消息的线程并没有阻塞,但也无法继续执行下去。要解决这种问题,需要在重试机制中引入随机性。
第11章 性能与可伸缩性
11.1 对性能的思考
11.1.1 性能与可伸缩性
11.1.2 评估各种性能权衡因素
11.2 Amdahl定律
在增加计算机资源的情况下,程序在理论上能够实现最高加速比,这个值取决于可并行组件与串行组件所占的比重。假定F是必须被串行执行的部分,那么根据Amdahl定律,在包含N个处理器的机器中,最高的加速比是:
要预测应用程序在某个多处理器系统中将实现多大的加速比,还需要找出任务中的串行部分。
11.2.1 示例:在各种框架中隐藏的串行部分
11.3 线程引入的开销
11.3.1 上下文切换
JVM和操作系统的开销。除此之外,当一个新的线程被切换进来时,它所需要的数据可能不在当前处理器的本地缓存中因此上下文切换将导致一些缓存缺失,因而线程在首次调度运行时会更加缓慢。
11.3.2 内存同步
内存栅栏(Memory Barrier)。内存栅栏可以刷新缓存,使缓存无效,刷新硬件的写缓冲,以及停止执行管道。现代的JVM能通过优化来去掉一些不会发生竞争的锁,从而减少不必要的同步开销。一些更完备的JVM能通过逸出分析(Escape Analysis)来找出不会发布到堆的本地对象引用。即使不进行逸出分析,编译器也可以执行锁粒度粗化(Lock Coarsening)将邻近的同步代码块用一个锁合并起来。
11.3.3 阻塞
JVM在实现阻塞行为时,可以采用自旋等待(通过循环不断地尝试获取锁,知道成功)或者通过操作系统挂起被阻塞的线程。
11.4 减少锁的持有时间
11.4.1 缩小锁的范围
来个例子:
由于在AttributeStore中只有一个状态变量attributes,因此可以通过将线程安全性委托给其他的类来进一步提升它的性能。通过用线程安全的Map(Hashtable,SynchronousMap或ConcurrentHashMap)来代替attributes, AttributeStore可以将确保线程安全性的任务委托给顶层的线程安全容器来实现。
11.4.2 减小锁的粒度
降低线程请求锁的频率,可以通过锁分解和锁分段等技术来实现。采用相互独立的锁来保护独立的状态变量。虽然能减小锁操作的粒度,实现更高的伸缩性,然而,使用的锁越多发生死锁的风险也就越高。如果一个锁要保护多个相互独立的变量,那么可以将这个锁分解为多个锁,并且每个锁只保护一个变量,从而提高可伸缩性。来个例子:
将上面的代码改一下,不用ServerStatus锁来保护用户状态和查血状态,而是每个状态都通过一个锁来保护,如下面的程序所示:
11.4.3 锁分段
在某些情况下,可以将锁分解技术进一步扩展为对一组独立对象上的锁分解,这中情况被称为锁分段。
(看起来很牛逼的样子)。锁分段的一个劣势在于:与采用单个锁来实现独占访问相比,要获取多个锁来实现独占访问将更加困难且开销更高。
11.4.4 避免热点域
锁分解和锁分段都能使不同的线程在不同的数据(或者同一个数据的不同部分)上操作,而不会相互干扰。如果程序采用锁分段技术,那么一定要表现出在锁上的竞争频率高于在锁保护的数据上发生竞争的频率。
当每个操作都请求多个变量时,锁的粒度将很难降低。这是在性能和可伸缩性之间的相互制衡的另一个方面,一些常见的优化措施,例如将一些反复计算的结果缓存起来,都会引入一些“热点域”,而这些热点域往往会限制可伸缩性。
11.4.5 一些替代独占锁的方法
第三种降低竞争锁的影响的技术就是放弃使用独占锁,从而有助于使用一种友好并发的方式来管理共享状态。例如使用并发容器,读-写锁,不可变对象以及原子变量。
11.4.6 检测cpu的利用率
11.4.7 向对象池说“不”
11.5 示例:比较Map的性能
在单线程环境下,ConcurrentHashMap的性能比同步的HashMap的性能略好一点,但在并发环境中则要好得多。在ConcurrentHashMap的实现中假设,大多是常用的操作都是获取某个已经存在的值,因此它对各种get操作进行了优化从而提供最高的性能和并发性。在同步的Map的实现中,可伸缩性的最主要阻碍在于整个Map中只有一个锁,因此每次只能有一个线程能够访问这个Map。不同的是,ConcurrentHashMap对大多数读操作并不会加锁,并且在写入操作以及其他一些需要锁的读操作中使用了锁分段技术。
11.6 减少上下文切换的开销
当任务在运行和阻塞这两个状态之间转换时,就相当于一个上下问切换。在服务器应用程序中,发生阻塞的原因之一就是在处理请求时产生的各种日志消息。为了说明如何通过减少上下文切换的次数来提高吞吐量,我们将对两种日志方法的调度进行分析。(这部分没看明白在分析什么....汗.... 先pass掉)
《java并发编程实战》读书笔记8--死锁,性能与可伸缩性,锁粒度锁分解锁分段的更多相关文章
- Java并发编程实战 读书笔记(一)
最近在看多线程经典书籍Java并发变成实战,很多概念有疑惑,虽然工作中很少用到多线程,但觉得还是自己太弱了.加油.记一些随笔.下面简单介绍一下线程. 一 线程与进程 进程与线程的解释 个人觉 ...
- 《Java并发编程实战》第十一章 性能与可伸缩性 读书笔记
造成开销的操作包含: 1. 线程之间的协调(比如:锁.触发信号以及内存同步等) 2. 添加�的上下文切换 3. 线程的创建和销毁 4. 线程的调度 一.对性能的思考 1 性能与可伸缩性 执行速度涉及下 ...
- Java并发编程实战 读书笔记(二)
关于发布和逸出 并发编程实践中,this引用逃逸("this"escape)是指对象还没有构造完成,它的this引用就被发布出去了.这是危及到线程安全的,因为其他线程有可能通过这个 ...
- java并发编程实战:第十一章----性能和可伸缩性
线程的最主要目的是提高程序的运行性能,但性能的提升会导致复杂性的提升,又会导致安全性和活跃性的风险 一.对性能的思考 提升性能意味着用更少的资源做更多地事情.要想通过并发来获得更好的性能,就要更有效地 ...
- 《java并发编程实战》笔记
<java并发编程实战>这本书配合并发编程网中的并发系列文章一起看,效果会好很多. 并发系列的文章链接为: Java并发性和多线程介绍目录 建议: <java并发编程实战>第 ...
- Java多线程编程实战读书笔记(一)
多线程的基础概念本人在学习多线程的时候发现一本书——java多线程编程实战指南.整理了一下书中的概念制作成了思维导图的形式.按照书中的章节整理,并添加一些个人的理解.
- Java并发编程艺术读书笔记
1.多线程在CPU切换过程中,由于需要保存线程之前状态和加载新线程状态,成为上下文切换,上下文切换会造成消耗系统内存.所以,可合理控制线程数量. 如何控制: (1)使用ps -ef|grep appn ...
- java并发编程实战《五》死锁
一不小心就死锁了,怎么办? 在上一篇文章中,我们用 Account.class 作为互斥锁,来解决银行业务里面的转账问题,虽然这个方案不存在并发问题,但是所有账户的转账操作都是串行的,性能太差. 向现 ...
- Java并发编程实践读书笔记(5) 线程池的使用
Executor与Task的耦合性 1,除非线程池很非常大,否则一个Task不要依赖同一个线程服务中的另外一个Task,因为这样容易造成死锁: 2,线程的执行是并行的,所以在设计Task的时候要考虑到 ...
- Java并发编程实战(4)- 死锁
在这篇文章中,我们主要讨论一下死锁及其解决办法. 目录 概述 死锁案例 死锁的原因和预防 破坏占用且等待条件 破坏不可抢占条件 破坏循环条件 使用等待-通知机制 Java中的等待-通知机制 条件曾经满 ...
随机推荐
- OLTP与OLAP比较【转】
OLTP与OLAP的介绍 数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing).联机分析处理OLAP(On-Line Analytical ...
- Linux查看内核和系统版本
1. 查看内核版本命令: 1) [root@q1test01 ~]# cat /proc/version Linux version 2.6.9-22.ELsmp (bhcompile@crowe.d ...
- 顺序统计:寻找序列中第k小的数
最直观的解法,排序之后取下标为k的值即可. 但是此处采取的方法为类似快速排序分块的方法,利用一个支点将序列分为两个子序列(支点左边的值小于支点的值,支点右边大于等于支点的值). 如果支点下标等于k,则 ...
- tomcat 访问400 的一种情况
tomcat 高版本对访问url做了较高的校验,如果url中包含特殊字符,tomcat会自动拦截,返回400错误.如果要包含特殊字符,需要事先进行转译. 我原来用的apache-tomcat-6.0. ...
- 无线局域网中RADIUS协议原理与实现
转载自:http://blog.csdn.net/jinhill/article/details/5901042 摘要 RADIUS协议是一个被广泛应用于网络认证.授权和计费的协议.本文在介绍了RA ...
- maven项目执行run as/maven install时提示找不到包
选中项目,右键 右键项目->MAVEN->Update Project,如下图 点击ok,clean相关项目,再打包.如果还是不行看一下你jdk 的版本和你编译的版本是否一致
- mixin模式特点
mixin模式特点: 1.单一功能, 2.不和基类关联,可以和任意基类组合,基类可以不和mixin关联就可以初始化成功 3.不使用 super() 用法
- 转【jenkins插件】
开源版本的Jenkins 具有三大能力:Master-Slave的分布式构建调度能力.Pipeline编排能力.强大的开源生态(插件)能力. 2017年4月,Jenkins创始人KK(Kohsuke ...
- CAS单点登录原理
转自 https://www.cnblogs.com/lihuidu/p/6495247.html 1.基于Cookie的单点登录的回顾 基于Cookie的单点登录核心原理: 将用户名密 ...
- 【BZOJ】3329: Xorequ
[题意]给定方程x^3x=2x,求<=x和<=2^x的满足方程的正整数个数. [算法]数位DP,矩阵快速幂 [题解]异或相当于不进位加法. 移项得,x^2x=3x,又因为x+2x=3x,所 ...