Java高并发程序设计学习笔记(一):并行简介以及重要概念
转自:https://blog.csdn.net/dataiyangu/article/details/86211544#_28
文章目录
为什么需要并行?
反对意见
大势所趋
几个重要的概念
同步(synchronous)和异步(asynchronous)
并发和并行
** 临界区 **
阻塞(Blocking)和非阻塞(Non-Blocking)
死锁(Deadlock)、饥饿(Starvation)和活锁(Livelock)![在这里插入图片描述](https://img-blog.csdnimg.cn/20190110074133373.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2RhdGFpeWFuZ3U=,size_16,color_FFFFFF,t_70)
并发级别
– 无障碍
– 无锁
– 无等待
有关并行的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. ...
随机推荐
- js携带参数跳转controller返回页面
upauth:function(){ var record = myForm.getRecord(); var companywyId = record.get("companyId&quo ...
- LC 851. Loud and Rich
In a group of N people (labelled 0, 1, 2, ..., N-1), each person has different amounts of money, and ...
- 依赖注入框架之dagger2
主页: https://github.com/google/dagger 历史 * Dagger1是由Square公司受到Guice(https://github.com/google/guice)启 ...
- 算法试题 - 找出最小 k 个数
题目 题目:输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 解析 思路1 这一题应用堆排序算法复杂度只有O(nlog k), ...
- [SPSS]如何利用spss进行单侧检验
根据网上经验来看,结论如下: 单双侧t检验,t值不变,p值除以2即为单侧p值.
- 深入学习重点分析java基础---第一章:深入理解jvm(java虚拟机) 第一节 java内存模型及gc策略
身为一个java程序员如果只会使用而不知原理称其为初级java程序员,知晓原理而升中级.融会贯通则为高级 作为有一个有技术追求的人,应当利用业余时间及零碎时间了解原理 近期在看深入理解java虚拟机 ...
- Android ADT安装与卸载
Android ADT安装 Eclipse 版本: Eclipse Java EE IDE for Web Developers. Version: Kepler Release Build id: ...
- 通过正则把文本里的链接加上a标签
把文本里的链接替换成a标签 function addLinks($text) { return preg_replace('/(http[s]?:\/\/[A-Za-z0-9]+\.[A-Za-z0- ...
- apache thrift 入门(一)
1.简介 Apache Thrift软件框架,是用来开发可扩展的跨语言的软件服务.通过软件堆栈和代码生成引擎相结合的方式来构建服务,使C++, Java, Python, PHP, Ruby, Erl ...
- XML JS Demo
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <m ...