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. ...
随机推荐
- echo、print、print_r之间的区别
echo php语句:可以一次输出多个值,多个值之间用逗号隔开:没有返回值,输出标量的值.print 函数:只能打印简单类型变量的值(标量,如int,string),返回值为布尔型print_r 函数 ...
- mysq乱码问题
不乱码的思想 liunx字符集→linux客户端字符集(例如:ssh)→mysql客户端字符集→mysql服务端字符集→库的字符集→表的字符集→程序字符集统一 mysql表跟库,库跟服务端字符集 li ...
- android 9.0以上charles https抓包
以前安装证书的方式无效了,必须将下载的证书复制到/system/etc/security/cacerts/目录, 步骤: 1.现在手机上安装好 chls.pro/ssl下载得到一个 charles-p ...
- Popover 弹出框
基础用法 Popover 的属性与 Tooltip 很类似,它们都是基于Vue-popper开发的,因此对于重复属性,请参考 Tooltip 的文档,在此文档中不做详尽解释. 设置索引ref,在按钮中 ...
- 使用EasyPrint实现不预览直接打印功能_非JS打印
插件地址 github 下载插件,安装后将在注册表中添加EasyPrint的协议 随后可以在开始->运行中输入EasyPrint://1&test 进行测试 参数分为两部分使用[&am ...
- Setup Python 开发环境和IPython的基本使用
目录 目录 前言 软件准备 Python交互式Shell 为Python Shell添加补全功能 IPython-400 IPython功能和特性基础 可直接使用部分的Bash指令 别名alias语法 ...
- centos升级glibc2.23编译安装
wget http://ftp.gnu.org/gnu/glibc/glibc-2.23.tar.gz tar -zxvf glibc-2.23.tar.gz cd glibc-2.23 mkdir ...
- JS事件中级 --- 拖拽
http://bbs.zhinengshe.com/thread-1200-1-1.html 要求:实现div块的拖拽 原理:拖拽过程中鼠标点和div块的相对位置保持不变. 需要理解三点: 1. 为什 ...
- EncryptionAndDecryptionC# 加密 解密
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- apache thrift 入门(一)
1.简介 Apache Thrift软件框架,是用来开发可扩展的跨语言的软件服务.通过软件堆栈和代码生成引擎相结合的方式来构建服务,使C++, Java, Python, PHP, Ruby, Erl ...