Java高并发程序设计学习笔记(一):并行简介以及重要概念
转自:https://blog.csdn.net/dataiyangu/article/details/86211544#_28
文章目录
为什么需要并行?
反对意见
大势所趋
几个重要的概念
同步(synchronous)和异步(asynchronous)
并发和并行
** 临界区 **
阻塞(Blocking)和非阻塞(Non-Blocking)
死锁(Deadlock)、饥饿(Starvation)和活锁(Livelock)
并发级别
– 无障碍
– 无锁
– 无等待
有关并行的2个重要定律
Amdahl定律(阿姆达尔定律)
Gustafson定律(古斯塔夫森)
为什么需要并行?
– 业务要求
– 性能
反对意见
– Linus Torvalds :忘掉那该死的并行吧!
– 需要有多么奇葩的想象力才能想象出并行计算的用武之地?
Linus Torvalds炮轰过的技术
– GNU Emacs
– GNOME
– HFS+ (Mac OS 文件系统)
– Java
• “本质上我看到的只是 Java 引擎在走下坡路,因为它别无去处。 ”1998年8月
• “我不关心Java。多么可怕的语言。“2011年11月
– C++
• “事实是,C++编译器不值得信任。整个C++异常处理从根本上是错误的。“2004年1月19日 “
• 尽管 C++ 可以用于原型或简单的 GUI 编程,但它不能使事情更简单。C 语言虽然并不精益于系统编程语言,但它积极鼓励你使用简单和直接的结构。 “2007年9月7日
• “C ++ 是一个可怕的语言。”2007年9月6日
– XML
– Solaris
– MINIX
Linus Torvalds :并行计算只有在图像处理和服务端编程2个领域可以使用,并且它在这2个 领域确实有着大量广泛的使用。但是在其它任何地方,并行计算毫无建树!
大势所趋
摩尔定律的失效
– 预计18个月会将芯片的性能提高一倍
– Intel CEO Barret单膝下跪对取消4GHz感到抱歉 • 在2004年秋季,Intel宣布彻底取消4GHz计划
– 虽然现在已经有了4GHZ的芯片,但频率极限已经逼近 10年过去了,我们还停留在4GHZ
顶级计算机科学家唐纳德·尔文·克努斯
– 在我看来,这种现象(并发)或多或少是由于硬件设计者 – 已经无计可施了导致的,他们将摩尔定律失效的责任 – 推脱给软件开发者。
并行计算还出于业务模型的需要
– 并不是为了提高系统性能,而是确实在业务上需要多个执行单元。 – 比如HTTP服务器,为每一个Socket连接新建一个处理线程
– 让不同线程承担不同的业务工作
– 简化任务调度
几个重要的概念
同步(synchronous)和异步(asynchronous)
同步异步是对于方法调用而言的。
同步调用会等待方法的返回,方法执行多久就要等待多久。
异步调用瞬间返回,但是调用并没有完成,会在后台起一个线程,所以不影响做下面的事情。
并发和并行
并发和并行的外在表象基本上是一致的。
并行:两个线程或者进程同时进行
并发:一会做事件a一会做事件b,如此重复调度
对于单核cpu来说只能是并发,对于多核cpu来说是可以并行的,但是对于外在表象来看,事件a和事件b不论是并行还是并发,都是在同时执行
临界区
– 临界区用来表示一种公共资源或者说是共享数据,可以被多个线程使用。但是每一次,只能有一个线程
使用它,一旦临界区资源被占用,其他线程要想使用这个资源,就必须等待。
阻塞(Blocking)和非阻塞(Non-Blocking)
– 阻塞和非阻塞通常用来形容多线程间的相互影响。比如一个线程占用了临界区资源,那么其它所有需要 这个资源的线程就必须在这个临界区中进行等待,等待会导致线程挂起。这种情况就是阻塞。此时,如 果占用资源的线程一直不愿意释放资源,那么其它所有阻塞在这个临界区上的线程都不能工作。
– 非阻塞允许多个线程同时进入临界区
阻塞是在操作系统层面被挂起,阻塞的方式性能比较差,据统计,如果一个线程在操作系统层面被挂起,做了上下文切换,需要八万个时间周期来做这件事情,所以不是一个特别好的办法,但是是最简单的方法,虽然效率不是很高。
死锁(Deadlock)、饥饿(Starvation)和活锁(Livelock)
死锁:a堵住了d,d堵住了c,c堵住了b,b堵住了a,a需要b开动,b需要c开动,c需要d开动,d需要a开动-----谁也不能动。
死锁虽然不好,但是是一个静态的问题,一旦死锁,所有的线程都停止,cpu的占用率是零
活锁:电梯里人想出来,外面的人想进去,都想避开,里面的人往左面靠,外面的人往右边靠,还是不能避开,里面的人往右面靠,外面的人往左边靠,如此往复。
又或者a线程需要资源1、2,b线程需要资源1、2,这个时候a抢到了1,b抢到了2,都不能工作,这个时候都释放出来,a又去抢到了2,b抢到了1,如此往复。
简言之,就是资源来线程之间跳来跳去,也无法进行下去。
活锁比死锁更难查找,因为是动态的问题。
饥饿:a线程优先级比b低,所以调度的时候调度不到a,就不能继续往下执行,就会饿死,或者资源竞争优先级比较低,也会导致饿死。
饥饿是指某一个或 者多个线程因为种 种原因无法获得所 需要的资源,导致 一直无法执行。
并发级别
阻塞:当一个线程进入临界区后,其他线程必须等待
非阻塞(下面三个)
– 无障碍
无障碍是一种最弱的非阻塞调度
自由出入临界区
无竞争时,有限步内完成操作
有竞争时,回滚数据有竞争时,回滚数据
好进不好出,很容易进去,但是进去发现很多线程竞争相同的资源的时候,会需要回滚数据,比如要读取xy,已经读过了x,读到y的时候发现在竞争,会从x重新读。
– 无锁
是无障碍的
保证有一个线程可以胜出
while (!atomicVar.compareAndSet(localVar, localVar+1)) {
localVar = atomicVar.get();
}
因为无障碍中,如果存在不断的竞争,将会所有的都出不来,所以无锁就需要每次竞争都能胜出一个,这样保证程序能够顺畅的执行下去。
– 无等待
无锁的
要求所有的线程都必须在有限步内完成 ,所有的线程都能在有线的事件内都从临界区出来。
无饥饿的,因为所有的线程都必须在有限步内完成 ,所以是无饥饿的。
举例子:
只有读线程没有写线程,就是无等待的。
如果有写线程的话,就会出现资源竞争也就是上面的无障碍的状态,怎么办呢?在每次写之前把数据拷贝一次副本,在写线程中拿到副本,修改副本,修改数据的过程可能需要点时间,可是修改的是副本不是原始的数据,所以在这个过程中的读线程仍然是无等待的。写线程也只是一直在写,所以也是无等待的。
最后需要时就是将副本覆盖原始数据而已。
有关并行的2个重要定律
Amdahl定律(阿姆达尔定律)
Gustafson定律(古斯塔夫森)
Amdahl定律(阿姆达尔定律)
– 定义了串行系统并行化后的加速比的计算公式和理论上限 – 加速比定义:加速比=优化前系统耗时/优化后系统耗时
在步骤二和步骤五的地方运用了并行
加速比=优化前系统耗时/优化后系统耗时=500/400=1.25
将上面的例子代入公式:f(串行比例)= 五分之三,这里默认两个cpu
由上面的公式可以得出:
增加CPU处理器的数量(n)并不一定能起到有效的作用 提高系统内可并行化的模块比重,合理增加并行处 理器数量(1-f),才能以最小的投入,得到最大的加速比
Gustafson定律(古斯塔夫森)
– 说明处理器个数,串行比例和加速比之间的关系
只要有足够的并行化,那么加速 比和CPU个数成正比
结论:两个结论虽然不同,但是总的来说就是要处理好n(cpu的个数)和f(串行化比例),因为公式中只和这两个参数有关系
Java高并发程序设计学习笔记(一):并行简介以及重要概念的更多相关文章
- Java高并发程序设计学习笔记(七):并行设计模式
转自:https://blog.csdn.net/dataiyangu/article/details/87123586 什么是设计模式架构模式设计模式代码模式(成例 Idiom)单例模式普通单例假如 ...
- Java高并发程序设计学习笔记(十一):Jetty分析
转自:https://blog.csdn.net/dataiyangu/article/details/87894253 new Server()初始化线程池QueuedThreadPoolexecu ...
- Java高并发程序设计学习笔记(十):并发调试和JDK8新特性
转自:https://blog.csdn.net/dataiyangu/article/details/87631574 多线程调试的方法使用Eclipse进行多线程调试线程dump及分析分析死锁案例 ...
- Java高并发程序设计学习笔记(五):JDK并发包(各种同步控制工具的使用、并发容器及典型源码分析(Hashmap等))
转自:https://blog.csdn.net/dataiyangu/article/details/86491786#2__696 1. 各种同步控制工具的使用1.1. ReentrantLock ...
- Java高并发程序设计学习笔记(三):Java内存模型和线程安全
转自:https://blog.csdn.net/dataiyangu/article/details/86412704 原子性有序性可见性– 编译器优化– 硬件优化(如写吸收,批操作)Java虚拟机 ...
- Java高并发程序设计学习笔记(二):多线程基础
转自:https://blog.csdn.net/dataiyangu/article/details/86226835# 什么是线程?线程的基本操作线程的基本操作新建线程调用run的一种方式调用ru ...
- Java高并发程序设计学习笔记(九):锁的优化和注意事项
转自:https://blog.csdn.net/dataiyangu/article/details/87612028 锁优化的思路和方法减少锁持有时间减小锁粒度锁分离锁粗化举个栗子举个栗子锁消除虚 ...
- Java高并发程序设计学习笔记(六):JDK并发包(线程池的基本使用、ForkJoin)
转自:https://blog.csdn.net/dataiyangu/article/details/86573222 1. 线程池的基本使用1.1. 为什么需要线程池1.2. JDK为我们提供了哪 ...
- Java高并发程序设计学习笔记(四):无锁
转自:https://blog.csdn.net/dataiyangu/article/details/86440836#1__3 1. 无锁类的原理详解简介:1.1. CAS1.2. CPU指令2. ...
随机推荐
- hibernate映射配置
1. 普通字段类型 2. 主键映射 单列主键映射 多列作为主键映射 主键生成策略,查看api: 5.1.2.2.1. Various additional generators 数据库: Q:一个 ...
- 算法试题 - 找出最小 k 个数
题目 题目:输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 解析 思路1 这一题应用堆排序算法复杂度只有O(nlog k), ...
- java初级之数组详解
一,数组的概念: 数组是为了存储同一种数据多个元素的集合,也可以看成是一个容器,数组既可以存储基本数据类型,也可以存储引用数据类型,数组是为了存储同种数据类型的多个值. 1.1.1,一维数组重点: 数 ...
- JavaScript日常学习1
您会经常看到 document.getElementById("id"). 这个方法是 HTML DOM 中定义的. DOM (Document Object Model)(文档对 ...
- 接入上一篇SSM框架整合示例
需要创建相应的包与文件夹 Book数据表作为本示例数据 搭建项目开始 首先有bean后 private int id; private String name; private int cnt; 第一 ...
- openLdap安装教程
环境 操作系统:centOS 7.0 OpenLDAP:2.4.X 安装 从yum源安装 yum install openldap openldap-servers openldap-clients ...
- notepad++ 插件说明(一)
notepad++插件说明(一) 1.xml插件安装 下载地址:https://sourceforge.net/projects/npp-plugins/files/XML%20Tools/Xml%2 ...
- python计算机二级考试知识点——文件操作
1. 文件的使用:文件打开.关闭和读写 python通过open函数打开一个文件,并返回一个操作文件的变量,语法形式如下: <变量名>=open(<文件路劲及文件名>,< ...
- Datafactory 学习笔记
1)插入汉字出现乱码的情况 select userenv('language') from dual: select * from V$NLS_PARAMETERS: 把下面变量名和变量值配置到系统环 ...
- /etc/passwd字段信息
root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nol ...