第三部分:活跃度、性能和测试
10 避免活跃度危险
如果所有线程以通用的固定秩序获得锁,程序就不会出现顺序锁死锁问题了。
当调用的方法不需要持有锁时,这被称为是“开放调用”。依赖于开放调用的类会具有更好的行为,并且比那些需要获得锁才能调用的方法相比,更容易与其他类合作。
在程序中尽量使用开放调用,依赖于开放调用的程序,相比于那些在持有锁时还调用外部方法的程序,更容易执行死锁自由度的分析。
10.2避免和诊断死锁
10.2.1尝试定时锁
另一项监测死锁和从死锁中恢复的技术,是使用每个显示Lock类中定时tryLock特性,来替代使用内部锁机制。
在内部锁的机制中,只要没有获得锁,就会永远保持等待,而显示的锁会使你能够定义超时的时间,在规定时间之后,tryLock还没有获得锁就返回失败。
通过使用超时,尽管这段时间比你预期能够获得锁的时间长很多,你仍然可以在意外发生后重新获得控制权。
10.2.2通过线程转储分析死锁
JVM使用“线程转储”来帮助你识别死锁的发生。
线程转储包括每个运行中线程的栈追踪信息,以及与之相应并随之发生的异常,锁信息等。
在生成线程转储前,JVM在表示“正在等待”关系的(有向)图中搜索循环来寻找死锁。如果发现了死锁,他就会包括死锁的识别信息,其中参与了哪些锁和线程,以及程序中造成了不良后果的锁请求发生在哪里。
10.3其他的活跃度危险
除了死锁,并发程度中其他活跃度危险:饥饿、丢失信号、活锁。
10.3.1饥饿
当线程访问它所需要的资源时,却被永久拒绝,以至于不能再继续进行,这样就发生了“饥饿”:最常见的是饥饿资源是CPU周期。
活锁
尽管没有被阻塞,线程依然不能继续,它不断尝试相同的操作,却总失败。
第11章性能和可伸缩性
改进性能意味着使用更少的资源做更多的事情。
引入多线程总会引入一些性能的开销:与协调线程相关的开销(加锁、信号、内存同步),增加上下文切换、线程的创建和消亡、调度的开销。
可伸缩性指的是:当增加计算资源时(如CPU、内存、存储器、I/O、带宽)吞吐量和生产量能相应得以改进。
避免不成熟的优化。首先使程序正确,然后再加快。如果它运行的不够快。
所有的并发程序都或多或少有一些串行资源。
线程引入的开销:
1》切换上下文:线程的调度需要操控OS和JVM中共享的数据结构
Unix的vmstat和Win下的platfmon工具都能报告上下文切换次数和内核占用的时间等信息。高内核占用率(10%)象征着频繁的调度活动,很可能是I/O阻塞、锁竞争引起。
2》内存同步:Synchronized和volatile提供的可见性保证要求:使用一个特殊的、名为“存储关卡memory barrier”的指令,来刷新缓存,使缓存无效;刷新硬件的写缓冲,并延迟执行的传递。
同步还造成了共享内存总线上的通信量(带宽有限、所有线程共享总线)
3》阻塞:非竞争的同步由JVM掌控;竞争的同步需OS活动,均为开销。
11.4减少锁的竞争:能改进性能和可伸缩性
并发程序中,对可伸缩性首要的威胁是独占的资源开销。
2个原因影响着锁的竞争性:锁被请求的频率;每次持有锁的时间
因此有3种方式来减少锁的竞争:减少持有锁的时间;减少请求锁的频率;用协调机制取代独占锁,从而允许更强的并发性。
11.4.1缩小锁的范围:快进快出
11.4.2减少锁的粒度
减少持有锁的时间比例的另一种方式是让线程减少调用它的频率。可以通过分拆锁和分离锁实现——采用相对独立的锁,守卫多个独立的状态变量,在改变之前,它们都是由一个锁守护的。
第12章测试并发程序
并发类的测试基本分为2类:安全性和活跃度(性能测试:吞吐量、响应性、可伸缩性)的测试。
第13章显示锁
在Java 5.0之前,用于调节共享对象访问的机制只有Synchronized与volatile。Java5.0提供了新选择:ReentrantLock(在内部锁局限时,提供可选的高级特性——内部锁不能中断那些正在等待获取锁的线程,并且请求锁失败的情况下,必须无限等待)
ReentrantLock实现了Lock接口,提供了与Synchronized相同的互斥和内存可见性的保证,获得ReentrantLock的锁与进入Synchronized块有相同的内存语义;释放ReentrantLock锁与退出Synchronized块有相同的内存语义。
13.1.1可轮询的和可定时的锁请求:由tryLock()实现
在内部锁中,死锁只能由重启来解决;tryLock()释放已获得的锁,再重新尝试。
13.1.2可中断的锁获取操作:在可取消的活动中取消:LockInterruptibly
13.3公平性
ReentrantLock构造函数中提供了2种公平性的选择:创建非公平锁(默认)和公平锁。
线程按顺序请求获得公平锁,然而允许一个非公平锁“闯入”:当请求这样的锁时,如果锁的状态变为可用,线程的请求可以在等待线程的队列中向前跳跃,获得该锁。
在内部锁不能够满足使用时,ReentrantLock才被作为更高级的工具。当你需要以下高级特性时,才应该使用:可定时的、可轮询的、与可中断的锁获取操作,公平队列或非块结构的锁,否则请用Synchronized。
13.5读写锁ReentrantReadWriteLock
有2个Lock对象的接口,一个用于读,一个用于写。读取ReadWriteLock守护的数据,必须先获取读锁,当需要修改ReadWriteLock守护的数据,须先获得写锁。
在公平锁中,选择权给等待时间最长的线程;如果锁由读锁获取,而另一个线程请求写入锁,则不再允许读者获取读锁,直到写锁被受理,并释放写锁。
第15章原子变量与非阻塞同步机制
在Java 5.0中,使用原子变量类(如AtomicInteger/AtomicReference)能高效的构建非阻塞算法.
原子变量提供了与volicatile类型变量相同的内存语义,同时还支持原子更新_使它能够更加理想的用于计算器,序列发生器,统计数据收录等.
15.1 锁的优势
Volatile变量与锁相比更轻量级的同步机制,因为它不会引起上下文切换和线程调度.
加锁还有一个缺点:当1个线程正在等待锁时,他不能做任何事情.
原子变量类型共有12个:计量器(AtomicInteger AtomicLong AtomicBoolean AtomicReference)、域更新器(field updater)、数组、复合变量。
第16章 Java存储模型JMM
JMM提供了JVM的一种最小保证:什么时候写入一个变量时会对其他线程可见。
16.1.1
一张架构的存储模型告诉了应用程序可以以它的存储系统中得到何种担保,用以在需要共享数据时,得到额外的存储协调保证。
Java提供了自己的存储模型,JVM会通过在适当的位置上插入存储关卡,来解决JVM与底层平台的存储模型的差异化
16.1.2重排序
各种能够引起操作延迟或错误执行的不同原因,都可以归为“重排序”
16.1.3Java存储模型的简介
Java存储模型的定义是通过动作的形式进行描述的。所谓动作,包括变量的读写,监视器的加锁与释放锁,线程的启动与拼接。
JMM为所有程序内部的动作定义了一个偏序关系,要想保住执行动作B的线程能够看到动作A的结果(无论AB是否在同一个线程),AB之间必须满足偏序关系。如果AB不满足偏序关系,则JVM可以对其任意的重排序。
相关推荐
这本"Java并发编程学习笔记"可能是作者在深入研究Java并发特性、工具和最佳实践过程中积累的心得体会。下面,我们将根据这个主题,探讨一些关键的Java并发编程知识点。 1. **线程与进程**:在多任务环境中,线程是...
Java并发编程是Java开发中必不可少的一部分,涉及到多线程、同步机制、线程池以及并发工具类等多个核心知识点。以下是对这些主题的详细说明: 1. **线程安全与锁 Synchronized 底层实现原理**: 线程安全是指在多...
Java并发编程学习笔记,研究JAVA并发多线程编程的一本教程,使用并发技术可以开发出并行算法,充分利用多处理器的计算能力,避免硬件资源浪费。目前,在JAVA并发编程方面的论述系统且内容详实的技术资料不太多,Java...
### Java并发编程实践笔记知识点详解 #### 一、保证线程安全的方法 1. **不要跨线程访问共享变量:** 当多个线程共享某个变量时,若其中一个线程修改了该变量,其他线程若没有正确同步,则可能读取到错误的数据。...
### Java并发编程学习笔记知识点详解 #### 一、Java并发编程概述 Java并发编程是指在Java应用程序中同时执行多个操作的技术。它通过多线程、线程池等机制实现资源的有效利用,提高程序运行效率。Java并发编程的...
Java并发编程是Java开发中的重要领域,它涉及到多线程、同步、锁机制、线程池等关键概念,是提高程序性能和效率的关键技术。在Java中,并发编程的运用可以充分利用多核处理器的能力,实现高效的多任务处理。以下是对...
Java并发编程系列心得笔记,可以参考,欢迎共同交流学习
本文将基于文档《Java并发编程与高并发解决方案-学习笔记***.pdf》中提供的内容,来详细阐述并发编程和高并发的基本概念、CPU多级缓存与缓存一致性、以及Java内存模型。 ### 并发与高并发概念 在现代多线程编程中...
Java并发编程 背景介绍 并发历史 必要性 进程 资源分配的最小单位 线程 CPU调度的最小单位 线程的优势 (1)如果设计正确,多线程程序可以通过提高处理器资源的利用率来提升系统吞吐率 ...
Java并发编程与高并发解决方案是开发高性能应用的关键技术。在基础篇中,主要涉及以下几个重要知识点: 1. **并发编程基础** - **并发**:并发是指在一个时间段内,多个线程交替执行,使得系统看起来像是同时处理...
Java并发编程 学习资料
java并发编程与并发解决方案是自己多年开发和学习的笔记,有助于(ˇˍˇ) 想~进一步提高的java开发工程师或架构师深入的学习java架构并发处理。同时,它也是 在实际工作中多年高并发解决方案和经验的总结
自己总结的java并发编程的笔记,绘制了详细的思维导图,每个思维导图中均有详细的博文解释,方便大家学习和理解,免费分享给大家。
### Java并发编程与高并发解决方案知识点总结 #### 一、并发与高并发基本概念 ##### 1.1 并发 - **定义**: 指一个程序在同一时刻拥有两个或更多的线程,这些线程可以在单核或多核处理器上运行。 - **单核处理器上...
"JUC并发编程学习笔记(硅谷)"很可能包含了关于Java并发工具集(Java Util Concurrency, JUC)的深入理解和实战经验。JUC是Java标准库提供的一套强大的并发处理工具,它极大地简化了多线程编程,提高了程序的可读性...
《Java并发编程之美》学习笔记 《Java concurrency programming》learning note
学习Java并发编程时,锁的概念是无法回避的。锁是同步的一种机制,用来控制多个线程访问共享资源的顺序。在Java中,锁主要有两种类型:内置锁和显示锁。内置锁使用synchronized关键字实现,而显示锁则是通过java....
Java并发库是Java平台中的核心组件,它为多线程编程提供了丰富的工具和接口,使得开发者能够高效、安全地实现并发程序。在Java并发库中,ExecutorService接口和相关的线程池是其核心部分,它们提供了线程管理和任务...
这篇“Java线程编程学习笔记(二)”很可能是对Java并发编程深入探讨的一部分,特别是涉及多线程示例的实践应用。我们将从标题、描述以及标签来推测可能涵盖的知识点,并结合"Multi-Threads Demo"这一压缩包文件名来...