学习笔记《Java多线程编程实战指南》三
3.1串行、并发与并行
1.串行:一件事做完接着做下一件事。
2.并发:几件事情交替进行,统筹资源。
3.并行:几件事情同时进行,齐头并进,各自运行直到结束。
多线程编程的实质就是将任务处理方式由串行改为并发,即实现并发化。
3.2竞态
状态变量:即类的实例变量、静态变量。可以被多个线程共享,也被称为共享变量。
共享变量: “可以”(不代表一定)被多个线程共同访问的变量。
多线程编程中对于同样的输入,程序输出的结果的正确性与时间有关的现象就被称为竞态,也就是说计算结果时而正确时而错误。
竞态常常是因为读取脏数据问题,即读取到一个过时的数据、丢失更新问题。二维表分析法是分析竞态问题的一种简单而有效的方法。
3.3竞态的模式与竞态产生的条件
3.3.1竞态的两种模式
read-modify-write(读-改-写) 和 check-then-act(监测而后行动)
if(sequence >= 999){ // 监测而后行动
sequence = 0;
} else {
sequence++; // 读-改-写
}
3.3.2竞态产生的条件
访问(读取、更新)同一组共享变量的多个线程所执行的操作相互交错。
3.3.3 消除竞态
1.将共享变量改为局部变量。
2.在访问共享变量的方法上加锁,synchronize关键字,使得该方法涉及的共享变量在任意时刻只能有一个线程访问。
3.4线程安全性
线程安全:如果一个类在单线程环境下能够运作正常,并且在多线程环境下,在其使用方不必为其做任何改变的情况下也能正常运行。不会导致竞态
非线程安全: 如果一个类在单线程环境下运行正常而在多线程环境下无法正常运行。会导致竞态,例如ArrayList、HashMap和SimpleDateFormat
3.4.1原子性
1.指访问(读、写)某个共享变量的操作从其执行线程以外的任何线程来看,该操作要么已经执行结束,要么尚未发生,即其他线程不会“看到”该操作执行了部分的中间效果。
2.实现原子性的方式有加锁synchronize关键字(软件锁),还有CAS指令(硬件锁)。
3.long型和double型以外的任何类型的变量的写操作都是原子操作。包括byte、short、int、char、boolean、float、String。为了保障long/double写操作的原子性,需要加volatile关键字修饰。 4.原子操作+原子操作 != 原子操作。
3.4.2可见性
可见性就是指一个线程对共享变量的更新的结果,对于读取相应共享变量的线程而言是否可见(能否读取到更新后的结果)的问题。
单处理器系统实现的多线程编程也可能出现可见性问题。
父线程在子线程启动之前对共享变量的更新对子线程的可见性是有保障的。父线程在子线程启动之后对共享变量的更新对子线程的可见性是没有保障的。
可见性的保障是通过使更新共享变量的处理器执行冲刷处理器缓存的动作,并使读取共享变量的处理器执行刷新处理器缓存的动作。java中通过对共享变量加volatile关键字修饰来保障可见性。
3.4.3有序性
感知顺序和源代码顺序一致,即有序性。volatile关键字、synchronized关键字都能够实现有序性。
可见性是有序性的基础。有序性影响可见性。
3.5上下文切换
一个线程被暂停,即被剥夺处理器的使用权,另外一个线程被选中开始或者继续运行的过程就叫做线程上下文切换。
切出:一个线程被剥夺处理器的使用权而被暂停运行。
切入:一个线程被操作系统选中占用处理器开始或者继续其运行。
上下文:切出和切入的时候操作系统需要保存和恢复相应线程的进度信息,这个进度信息就被称为上下文。
多线程编程想必单线程编程来说,意味着更多的上下文切换,因此,多线程编程不一定比单线程的计算效率更高。
3.5.1上下文切换的分类和具体诱因
自发性上下文切换:Thread.sleep(); Object.wait();Thread.yield();Thread.join();LockSupport.park();I/O操作或者等待其他线程持有的锁。
非自发性上写文切换:时间片用完了;线程优先级更高的线程需要被运行;java虚拟机的垃圾回收动作。
3.6线程的活性故障
线程活性故障:由于资源稀缺性或者程序自身的原因和缺陷导致线程一直处于非RUNNABLE状态,或者线程虽然处于RUNNABLE状态但是其要执行的任务却一直无法进展的现象叫做线程活性故障。
死锁:例如:一个线程X持有资源A的时候等待另一个线程释放资源B。而另一个线程Y在持有资源B的时候却等待线程X释放资源A。死锁的外在表现就是当事线程的生命周期状态永远处于非RUNNABLE状态。
锁死:例如:一个线程X始终在等待资源或者锁而一直处于非RUNNABLE状态。
活锁:例如:一个线程在执行时,一直无法结束而一直处于RUNNABLE状态,并且线程所要执行的任务却丝毫没有进展。即线程可能一直在做无用功。
饥饿:饥饿就是线程因无法获得其所需的资源而使得任务执行无法进展的现象。
3.7资源争用与调度
资源的争用与调度:由于资源的稀缺性或者资源本身的特性,我们往往需要在多个线程间共享同一个资源。
排他性资源:
资源争用:在一个线程占用一个排他性资源进行访问(读、写操作)而未释放其对资源所有权的时候,其他线程试图访问该资源的现象就被称为资源争用。争用是在并发环境下产生的一种现象。
资源调用的一种常见策略就是排队。资源调度器内部维护一个等待队列。通常,被存入等待队列的线程会被暂停,当相应的资源被其持有线程释放时,等待队列中的一个线程会被选中唤醒而再次获得申请自愿的机会。被唤醒的线程如果申请到资源的独占权,那么该线程会从等待队列中移除。
公平的调度策略不允许插队的现象,而非公平的调度策略则允许允许插队的现象。即一个线程释放器资源独占权的时候,等待队列中的一个线程会被唤醒再次申请相应的资源。极端的情况下非公平调度策略可能导致等待队列中的线程永远无法获得其所需的资源,会出现饥饿。
学习笔记《Java多线程编程实战指南》三的更多相关文章
- Java多线程编程实战指南(核心篇)读书笔记(三)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76686044冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- Java多线程编程实战指南(核心篇)读书笔记(五)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76730459冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- Java多线程编程实战指南(核心篇)读书笔记(四)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76690961冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- Java多线程编程实战指南(核心篇)读书笔记(二)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76651408冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- Java多线程编程实战指南(核心篇)读书笔记(一)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76422930冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- 《Java多线程编程实战指南(核心篇)》阅读笔记
<Java多线程编程实战指南(核心篇)>阅读笔记 */--> <Java多线程编程实战指南(核心篇)>阅读笔记 Table of Contents 1. 线程概念 1.1 ...
- 学习笔记《Java多线程编程实战指南》二
2.1线程属性 属性 属性类型及用途 只读属性 注意事项 编号(id) long型,标识不同线程 是 不适合用作唯一标识 名称(name) String型,区分不同线程 否 设置名称有助于 ...
- 学习笔记《Java多线程编程实战指南》一
1.1什么是多线程编程 多线程编程就是以线程为基本抽象单位的一种编程范式,和面向对象编程是可以相容的,事实上Java平台中的一个线程就是一个对象.多线程编程不是线程越多越好,就像“和尚挑水”的故事一样 ...
- Java多线程编程实战指南 核心篇 读书笔记
锁 volatile CAS final static 原子性保障 具备 具备 具备 不涉及 不涉及 可见性保障 具备 具备 不具备 不具备 具备① 有序性保证 具备 具备 不涉及 具备 具备② 上下 ...
随机推荐
- configparser模块(ini配置文件生成模块)
config = configparser.ConfigParser() #初始化config对象 [DEFAULT] #设置默认的变量值,初始化 config["DEFAULT" ...
- Vue中添加新的路由并访问
1.搭建好Vue脚手架(这里使用的版本是Vue2.0) 2.在代码编辑器(这里使用的是Sublime Text)打开项目文件夹 3.在文件目录src中的component下创建一个新的vue页面,写入 ...
- GitHub看板系统(Project)
/********************************************************************** * GitHub看板系统(Project) * 说明: ...
- docker中的oracle-11g-安装配置
docker镜像:wnameless/oracle-xe-11g 启动镜像的命令: docker run -d -v /data/oracle_data:/data/oracle_data -p 11 ...
- new和malloc
1.申请的内存所在位置 自由存储区(free store)是C++基于new操作符的一个抽象概念,凡是new进行内存申请,该内存为自由存储区.堆是操作系统中的术语,是操作系统所维护的一块特殊内存,用于 ...
- MHA-Atlas-MySQL高可用集群2
MHA脚本管理方式 (1)获取管理脚本master_ip_failover 提示:yum安装的manager是没有这个脚本的. 我们需要从manager的源码包里复制一个. [root@mysql ...
- ubuntu16.04 安装java
1.从官网下载 jdk-8u191-linux-x64.tar.gz(https://www.oracle.com/technetwork/java/javase/downloads/jdk8-dow ...
- 17. Debuggers (调试器 5个)
反编译是安全研究的重要组成部分. 它将帮助您解剖Microsoft补丁,以发现他们无法告诉您的默认修复的错误,或更仔细地检查服务器二进制文件以确定为什么您的漏洞利用不起作用. 许多调试器都可用,但ID ...
- ZZFAFA_BilibiliMusic_DownUrl
OneDrive_DownFileUrl: FHProductionHK-BGM:https://1drv.ms/f/s!Ajs97XY1QSQ8cPXo36h4AK9XG7k CABAL&A ...
- 修复因为存储空间问题引起的nexus 服务启动异常
故障描述 因为nexus所在服务器存储空间满了, 做了部分清理操作,结果nexus 启动异常,提示错误信息基本类似如下: build 285537d2767275f460df32c6a3be01b ...