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)。它的基本思想是,对数据的读可以不加控制。因此,所有的读线程都是无等待的,它们既不会被锁定等待也不会引起任何冲突。但在写数据的时候,先取得原始数据的副本,接着只修改副本数据(这就是为什么读可以不加控制),修改完成后,在合适的时机回写数据。

原文地址:https://www.cnblogs.com/nangonghui/p/8872564.html

时间: 2024-08-05 15:52:29

java并发的基本概念和级别的相关文章

java并发编程基础概念

1.什么是进程和线程 1.1 进程是程序运行资源分配的最小单位 进程是操作系统进行资源分配的最小单位,其中资源包括:CPU.内存空间.磁盘IO等,同一进程中的多个线程共享该进程中的全部系统资源,而进程和进程之间是相互独立的.进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位. 进程是程序在计算机上的一次执行活动.当你运行一个程序,你就启动了一个进程.显然,程序是死的.静态的,进程是活的.动态的.进程可以分为系统进程和用户进程.凡是用于完成操作

Java并发编程核心概念一览

并行相关概念 同步和异步 同步和异步通常来形容一次方法的调用.同步方法一旦开始,调用者必须等到方法结束才能执行后续动作:异步方法则是在调用该方法后不必等到该方法执行完就能执行后面的代码,该方法会在另一个线程异步执行,异步方法总是伴随着回调,通过回调来获得异步方法的执行结果. 并发和并行 很多人都将并发与并行混淆在一起,它们虽然都可以表示两个或者多个任务一起执行,但执行过程上是有区别的.并发是多个任务交替执行,多任务之间还是串行的:而并行是多个任务同时执行,和并发有本质区别. 对计算机而言,如果系

Java并发编程-基础概念全解

1.基础 1.1.什么是进程和线程 进程和线程都是操作系统所运行的程序运行的基本单元.进程可以说是是线程的集合. 进程:从系统资源讲,进程都有自己独立的地址空间,一个进程的崩溃不会影响另一个进程的执行. 线程:进程中的一个执行路径,一个进程中可以同时有多个线程在执行,当其中一个线程对公共资源做了修改,其他线程是可以看到的. 1.2.什么是并行和并发 并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时. 并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正

2015.6.10(java并发)

今天复习熟悉了Java并发的一些概念. 程序:系统要完成的一个任务,就是一个程序: 进程:每个运行中的程序就是一个进程,Windows任务管理器上可以看到每一个进程,Linux下使用ps –e命令可以查看当前运行的所有进程: 线程:每个运行的程序(进程)内部可能会包含多个顺序执行流,每个执行流就可以看做线程. 1. 进程的特性: 1) 独立性:进程是系统中独立存在的实体,它可以拥有自己独立的资源,每个进程都拥有自己私有的地址空间,其他进程不能访问这个进程空间内的数据. 2) 动态性:进程与程序的

java并发知识点

前言 先列出java并发涉及的知识点,后面再慢慢补. java并发 1 常见概念 进程/线程 进程:程序执行的实体,操作系统资源调度资源分配的基本单元 线程:程序执行的最小单元,拥有独立的堆栈和局部变量等属性,可以共享进程的资源 同步(Synchronous)/异步(Asynchronous) 同步是串行执行,阻塞 异步是并行执行,非阻塞 并发/并行 并发:多个任务交替执行 并行:多个任务同时执行 临界区 阻塞(Blocking)/非阻塞(Non-Blocking) 死锁/饥饿/活锁 JMM(j

【java并发编程实战】-----线程基本概念

学习Java并发已经有一个多月了,感觉有些东西学习一会儿了就会忘记,做了一些笔记但是不系统,对于Java并发这么大的"系统",需要自己好好总结.整理才能征服它.希望同仁们一起来学习Java并发编程,共同进步,互相指导. 在学习Java并发之前我们需要先理解一些基本的概念:共享.可变.线程安全性.线程同步.原子性.可见性.有序性. 共享和可变 要编写线程安全的代码,其核心在于对共享的和可变的状态进行访问. "共享"就意味着变量可以被多个线程同时访问.我们知道系统中的资

个人知识点总结——Java并发

Java并发实在是一个非常深的问题,这里仅仅简单记录一下Java并发的知识点.水太深.假设不花大量的时间感觉全然hold不住,可是眼下的精力全然不够,兴趣也不在这 什么是线程安全性 某个类的行为和其规范全然一致 当多个线程訪问某个类时.不管运行时环境採用何种调度方式或者这些线程将怎样交替运行.而且在主调代码中不须要不论什么额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的 原子操作(Atomic Operation) 原子操作是指不会被线程调度机制打断的操作,这样的操作一旦

Java 并发基础

Java 并发基础 线程简述 线程是进程的执行部分,用来完成一定的任务; 线程拥有自己的堆栈,程序计数器和自己的局部变量,但不拥有系统资源, 他与其他线程共享父进程的共享资源及部分运行时环境,因此编程时需要小心,确保线程不会妨碍同一进程中的其他线程; 多线程优势 进程之间不能共享内存,但线程之间共享内存/文件描述符/进程状态非常容易. 系统创建进程时需要为该其分配很多系统资源(如进程控制块),但创建线程的开销要小得多,因此线程实现多任务并发比进程效率高. Java语言内置多线程支持,而不是单纯采

特约稿件 Java并发教程(Oracle官方资料)

本文是Oracle官方的Java并发相关的教程,感谢并发编程网的翻译和投递. (关注ITeye官微,随时随地查看最新开发资讯.技术文章.) 计算机的使用者一直以为他们的计算机可以同时做很多事情.他们认为当其他的应用程序在下载文件,管理打印队列或者缓冲音频的时候他们可以继续在文字处理程序上工作.甚至对于单个应用程序,他们任然期待它能在在同一时间做很多事情.举个例子,一个流媒体播放程序必须能同时完成以下工作:从网络上读取数字音频,解压缩数字音频,管理播放和更新程序显示.甚至文字处理器也应该能在忙于重