学习笔记《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 原子性保障 具备 具备 具备 不涉及 不涉及 可见性保障 具备 具备 不具备 不具备 具备① 有序性保证 具备 具备 不涉及 具备 具备② 上下 ...
随机推荐
- Spring Boot 异步运用
使用@Async标签 导入包 org.springframework.scheduling.annotation.Async 并配置并发线程池asyncTaskConfig 实现AsyncConfig ...
- Web服务器软件 (Tomcat)
1.什么是服务器? 安装了服务器的软件的计算机 服务器软件:接收用户的请求(request),处理请求,做出响应. Web服务器软件:接收用户的请求(request),处理请求,做出响应,再Web服务 ...
- SQL server 的身份验证模式
windows身份验证(本机的ip地址或者localhost 或者.或者127.0.0.1) SQL Server身份验证(用户名和密码登录) 常见的错误代码18456(登录失败)和18470(账户被 ...
- Dart 的function
方法的定义 返回类型 方法名 (参数1 ,参数2 ,...){ 方法体 返回值 } => 的使用
- ubuntu18.04 下利用conda安装opencv3
ubuntu18.04 下利用conda安装opencv3 安装opencv3 conda install -c https://conda.anaconda.org/menpo opencv3 出现 ...
- javascript的加减乘除结果会有误差,在两个浮点数相加的时候会比较明显。以下函数返回较为精确的计算结果
加法函数(返回值:arg1加arg2的精确结果 ) function accAdd (arg1, arg2) { var r1, r2, m, c try { r1 = arg1.toString( ...
- 查看那些进程使用了swap
https://blog.csdn.net/xiangliangyu/article/details/8213127$ sudo pacman -S iotop https://blog.longwi ...
- [小明打联盟][斜率/单调队列 优化dp][背包]
链接:https://ac.nowcoder.com/acm/problem/14553来源:牛客网 题目描述 小明很喜欢打游戏,现在已知一个新英雄即将推出,他同样拥有四个技能,其中三个小技能的释放时 ...
- requests 爬虫
爬虫 常用爬虫爬取网页,但如果一直爬取会被ban掉,因此需要对爬虫进行一些改进反反爬 使用requests和beautifulsoup4构建爬虫,1.随机user-agent:2.ip代理:4.coo ...
- ACM山东工商 数据结构与算法 第3章 双向栈的操作
#include <stdio.h>#include <stdlib.h> #define SIZE 20//1左 偶 typedef struct hold{ int s ...