java并发的基本概念和级别
并发的概念:
并发(Concurrency)和并行(Parallelism)
并发偏重于多个任务交替执行,而多个任务之间有可能还是串行的。而并行是真正意义上的“同时执行”。严格意义上来说,并行的多个任务是真实的同时执行,而对于并发来说,这个过程只是交替的,一会儿运行任务A一会儿执行任务B,系统会不停地在两者间切换。但对于外部观察者来说,即使多个任务之间是串行并发的,也会造成多任务间是并行执行的错觉。真实的并行也只可能出现在拥有多个CPU的系统中(比如多核CPU)。
临界区
临界区用来表示一种公共资源或者说是共享数据,可以被多个线程使用。但是每一次,只能有一个线程使用它,一旦临界区资源被占用,其他线程要想使用这个资源,就必须等待。
阻塞(Blocking)和非阻塞(Non-Blocking)
阻塞和非阻塞通常用来形容多线程间的相互影响。比如一个线程占用了临界区资源,那么其他所有需要这个资源的线程就必须在这个临界区中进行等待。等待会导致线程挂起,这种情况就是阻塞。非阻塞的意思与之相反,它强调没有一个线程可以妨碍其他线程执行。所有的线程都会尝试不断前向执行。
死锁(Deadlock)、饥饿(Starvation)和活锁(Livelock)
死锁、饥饿和活锁都属于多线程的活跃性问题。如果发现上述几种情况,那么相关线程可能很难再继续往下执行了。
死锁是几个线程彼此之间相互占用了其它线程的资源,如果大家都不愿意释放自己的资源,那么这个状态将永远维持下去。与死锁相比,饥饿还是有可能在未来一段时间内解决的(比如高优先级的线程已经完成任务,不再疯狂的执行)。活锁是一种有趣的情况,比如当你要坐电梯下楼,电梯到了,门开了,这时你正准备出去。但很不巧的是,门外一个人挡着你的去路,他想进来。然后你们向同一个方向礼让,结果,你们俩就又撞上了……
并发的级别
由于临界区的存在,多线程之间的并发必须受到控制。根据控制并发的策略,可以把并发的级别进行分类,大致上可以分为阻塞、无饥饿、无障碍、无锁、无等待几种。
阻塞(Blocking)
一个线程是阻塞的,那么在其他线程释放资源之前,当前线程无法继续执行。当我们使用synchronized关键字,或者重入锁时就会产生阻塞的线程。无论是synchronized或者重入锁,都会试图在执行后续代码前,得到临界区的锁,如果得不到,线程就会被挂起等待,直到占有了所需资源为止。
无饥饿(Starvation-Free)
这个取决于线程之间是否有优先级的存在,如果系统允许高优先级的线程插队。这样有可能导致低优先级线程产生饥饿。
无障碍(Obstruction-Free)
无障碍是一种最弱的非阻塞调度。两个线程如果是无障碍的执行,那么他们不会因为临界区的问题导致一方被挂起。换言之,大家都进入临界区了。那么如果一起修改共享数据,把数据改坏了可怎么办呢?对于无障碍的线程来说,一旦检测到这种情况,它就会立即对自己所做的修改进行回滚,确保数据安全。如果说阻塞的控制方式是悲观策略,相对来说非阻塞的调度就是一种乐观的策略。
从这个策略中也可以看到,当临界区中存在严重的冲突时,所有的线程可能都会不断地回滚自己的操作,而没有一个线程可以走出临界区。这种情况会影响系统的正常执行。
一种可行的无障碍实现可以依赖一个“一致性标记”来实现。线程在操作之前,先读取并保存这个标记,在操作完成后,再次读取,检查这个标记是否被更改过,如果两者是一致的,则说明资源访问没有冲突。如果不一致,则说明资源可能在操作过程中与其他写线程冲突,需要重试操作。而任何对资源有修改操作的线程,在修改数据前,都需要更新这个一致性标记,表示数据不再安全。
无锁(Lock-Free)
无锁的并行都是无障碍的。在无锁的情况下,所有的线程都能尝试对临界区进行访问,但不同的是,无锁的并发保证必然有一个线程能够在有限步内完成操作离开临界区,一个典型的特点是可能会包含一个无穷循环。在这个循环中,线程会不断尝试修改共享变量。如果修改成功,程序退出,否则继续尝试修改。但无论如何,无锁的并行总能保证有一个线程是可以胜出的。至于临界区中竞争失败的线程,它们则不断重试,直到自己获胜。如果总是尝试不成功,则会出现类似饥饿的现象,线程会停止不前。
无等待(Wait-Free)
无锁只要求有一个线程可以在有限步内完成操作,而无等待则在无锁的基础上更进一步进行扩展。它要求所有的线程都必须在有限步内完成,这样就不会引起饥饿问题。如果限制这个步骤上限,还可以进一步分解为有界无等待和线程数无关的无等待几种,它们之间的区别只是对循环次数的限制不同。一种典型的无等待结构就是RCU(Read-Copy-Update)。它的基本思想是,对数据的读可以不加控制。因此,所有的读线程都是无等待的,它们既不会被锁定等待也不会引起任何冲突。但在写数据的时候,先取得原始数据的副本,接着只修改副本数据(这就是为什么读可以不加控制),修改完成后,在合适的时机回写数据。
java并发的基本概念和级别的更多相关文章
- Java并发(一):基础概念
对于Java并发,我也是属初学阶段,用的参考书是:"Java并发编程实战",写博时也参考了很多类似主题的博客,博主意在记录自己的学习路程,供网友讨论学习之用; 周末写的差不多了,今 ...
- java并发编程基础概念
本次内容主要讲进程和线程.CPU核心数和线程数.CPU时间片轮转机制.上下文切换,并行和并发的基本概念以及并发编程的好处和注意事项,为java并发编程打下扎实基础. 1.什么是进程和线程 1.1 进程 ...
- Java并发(二):基础概念
并发编程的第二部分,先来谈谈发布(Publish)与逸出(Escape); 发布是指:对象能够在当前作用域之外的代码中使用,例如:将对象的引用传递到其他类的方法中,对象的引用保存在其他类可以访问的地方 ...
- Java并发编程核心概念一览
作者博客地址 https://muggle.javaboy.org. 并行相关概念 同步和异步 同步和异步通常来形容一次方法的调用.同步方法一旦开始,调用者必须等到方法结束才能执行后续动作:异步方法则 ...
- Java并发编程 - 基本概念
在开始我们的并发编程前,我们必须预热一下,一些基本概念必须了解. 1. 同步(Synchronous) / 异步(Asynchronous) 同步和异步都指一次方法调用. 同步:方法开始后,调用者必须 ...
- java并发知识点
前言 先列出java并发涉及的知识点,后面再慢慢补. java并发 1 常见概念 进程/线程 进程:程序执行的实体,操作系统资源调度资源分配的基本单元 线程:程序执行的最小单元,拥有独立的堆栈和局部变 ...
- Java并发程序设计(一) 基础概念
Java并发程序设计(一) 基础概念 一.必须知道的几个概念 一)同步(Synchronous)和异步(Asynchronous) 同步:同步方法调用一旦开始,调用者必须等到方法调用返回后,才能继续后 ...
- 【java并发编程实战】-----线程基本概念
学习Java并发已经有一个多月了,感觉有些东西学习一会儿了就会忘记,做了一些笔记但是不系统,对于Java并发这么大的"系统",需要自己好好总结.整理才能征服它.希望同仁们一起来学习 ...
- java 并发性和多线程 -- 读感 (一 线程的基本概念部分)
1.目录略览 线程的基本概念:介绍线程的优点,代价,并发编程的模型.如何创建运行java 线程. 线程间通讯的机制:竞态条件与临界区,线程安全和共享资源与不可变性.java内存模型 ...
随机推荐
- Javascript MV framework 对比
Javascript 最近的framework笔记多,大致可分以下3类.单向绑定简单直接.ajax从service拿数据传递给viewtemplate进行绑定.当然这个过程也可以在服务器端来做,.ne ...
- Linux libusb 安装及简单使用
Linux libusb 安装及简单使用 一.参考文档: . libusb1 fails do_configure task with “udev support requested but libu ...
- swift实现label换行
so easy 换行的实质为在字符串中添加"\n" so, understand???
- NOI 模拟赛
T1 Article 给 $m$ 个好串,定义一个字符串分割方案是好的当且仅当它分割出来的子串中"是好串的子串"的串长占原串串长超过 85%,定义一个好的分割方案的权值为这种分割方 ...
- HDU - 6521 Party (SYSU校赛K题)(线段树)
题目链接 题意:n个人排成一列,一开始他们互不认识,每次选[l,r]上的人开party,使他们互相认识,求出每次party之后新互相认识的人的对数. 思路:把“互相认识”变成单向连边,只考虑左边的人对 ...
- .NET Core 和 .NET Framework 中的 MEF2
MEF,Managed Extensibility Framework,现在已经发布了三个版本了,它们是 MEF 和 MEF2. 等等!3 去哪儿了?本文将教大家完成基于 MEF2 的开发. ME ...
- 接口测试基础——第7篇 简单的Python知识普及(二)之装饰器
今天我们来学习python里面的“装饰器” 1.我在函数test运行前想先打印一些内容怎么办? def func(param): print u"打印的内容" para ...
- windows常用的命令行操作
1.切换当前目录 cd 路径 --change directory 2.创建目录 mkdir ‘文件名’ --make directory touch '文件名' --创建文件(多个文件用,分隔) 3 ...
- UVA11137 Ingenuous Cubrency
题意 PDF 分析 考虑dp. 用\(d(i,j)\)表示用不超过i的立方凑成j的方案数. \(d(i,j)=d(i-1,j)+d(i,j-i^3)\) 时间复杂度\(O(IN+T)\) 代码 #in ...
- c/c++程序设计涉及的一些知识点
c/c++程序设计涉及的一些知识点 c中的printf函数 main(){ int b = 3; int arr[]= {6,7,8,9,10}; int * ptr = arr; *(ptr++) ...