多线程-并发编程相关概念

JMM

并发编程模型的分类

  • 提出这些模型的原因是为了解决线程(并发活动的执行体)之间如何通信以及线程之间如何同步
  • 命令式编程之中,线程之间的通信机制有两种:共享内存、消息传递。
  • JAVA 的并发采用的是共享内存模型,所以JAVA线程之间的通信是隐式进行的,整个通信的过程对于程序员来说是完全透明的!
共享内存
  • 线程之间共享程序的公共状态线程之间通过写-读内存中的公共状态来隐式的进行通信
  • 在该模型中,线程同步是显式进行的,程序员必须显式指定某个方法或某段代码需要在线程之间互斥执行。
消息传递
  • 线程之间没有公共状态线程之间必须通过明确的发送消息来显式的进行通信
  • 在该模型中,由于消息的发送必须在消息接收之前,所以同步是隐式进行的。

Java 内存模型的抽象

  • 局部变量、方法定义参数、异常处理参数都不会在线程之间共享,所以他们不会有内存可见性问题。
  • JAVA 线程之间的通信由 JAVA 内存模型(JMM)控制。
  • 同时他们也不受内存模型的影响。
  • JMM 决定一个线程对共享变量的写入何时对另一个线程可见。
  • 它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。
堆内存
  • 主要用来存储:所有实例域、静态域、数组元素
  • 堆内存在线程之间是共享的。
如何抽象
  • 线程之间的共享变量存储在主内存之中。
  • 每个线程都有对应的一个私有本地内存
  • 本地内存存储的是当前拥有这个本地内存的线程读写的共享变量的副本
如何通信
  • 通过如下内存抽象模型来分析。
  • 下图中 A 线程是如何和 B 线程通信的。
  • 一:线程 A 把本地内存 A 中的共享变量副本更新到主存中。
  • 二:线程 B主存中把之前 A线程更新过的共享变量读取出来。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-55rrNkgq-1643078177017)(C:\Users\noblegasesgoo\AppData\Roaming\Typora\typora-user-images\image-20211111200142439.png)]

应用的场景

  • 我们现在并发主要用在两大块:
    • 图像处理。
    • 服务端程序,而我们JAVA一般都是开发服务端程序,所以绕不开高并发的学习以及使用。

管程

  • Monitor 监视器,Java 中平时所说的 ,就是操作系统中所说的监视器
  • 一种同步机制,保证同一时间,只有一个线程能够访问被保护的临界区
  • JVM 中进行同步操作,基于进入和退出 Monitor 对象来实现。

与并发有关的几个概念

  • 同步:同步的方法只要开始调用,调用者就必须等到方法调用返回才能继续进行后续的工作。
  • 异步:异步方法就不用等到方法调用返回就可以继续进行后续的工作。
  • 并行:同时执行。
  • 并发:看起来是同时执行,但其实是某一时段多个任务以极快的速度交替执行。

与共享资源有关的几个概念

  • 临界区:每个线程或进程访问临界资源的那段代码。

  • 临界资源:一种公共资源,可以被多个线程访问,但是一次只能一个线程访问。

    • 好比单间厕所,一旦有人使用,外面的人就得等着,等到这个人出来才能下一个人进去。
  • 阻塞:当一个线程占用了临界区的资源后,后续想要访问这个临界区的线程只能在这个临界区中等待,等待会导致线程被挂起,这就是阻塞。

  • 非阻塞:和阻塞不同,等待时线程不被挂起,而是一直尝试执行。

多线程活跃性的问题

  • 死锁:最不希望看到的情况,也就是最糟糕的情况,例如,A等B释放所需资源的同时B也等着A释放所需资源。
  • 活锁:线程之间互相让步,会在某些时刻主动释放资源。
  • 饥饿:一个或者多个线程因为一些原因无法获得当前所需的资源而导致其一直无法执行。
    • 就像线程或进程都有优先级的概念,一个优先级高的线程或进程一直在抢占并且使用资源,导致优先级低的线程或进程没法获得所需的资源导致饥饿。

并发级别

  • 由于临界区的存在,我们必须对多线程之前对临界区并发访问进行控制

  • 我们可以根据并发的策略,把并发级别分为五个级别:

    • 阻塞无饥饿无障碍无锁无等待
  • 阻塞

    • 悲观策略,一个线程占用临界资源,其它线程就需要挂起等待,无法继续执行下去,比如在 JAVA 中的 synchronized 或者是 重入锁
  • 无饥饿

    • 悲观策略,阻塞调度,进程或进程之间有优先级的概念,按照优先级来进行线程或进程的调度,这也会产生优先级低的进程或线程产生饥饿。
    • 我们可以通过锁是公平的,按照先来后到的规则进行线程调度。
  • 无障碍

    • 乐观策略,非阻塞调度,不同的线程都可以进入临界区,读线程可以随意读,但是写线程得判断当前资源有没有发生竞争,也就是有没有中途被别的线程修改,如果修改了就进行回滚
  • 无锁

    • 解决了无障碍并发级别的缺点。
    • 通过无障碍加一致性标志来实现。
    • 在修改资源之前先保存这个标记,再修改数据。
    • 修改完数据之后,我们再看看先前的标志有没有被别的线程篡改,如果是被篡改过,那就说明,发生了资源的争抢,此时就得判断是回滚还是沿用。
    • 保证至少有一个线程可以走出临界区
    • 一般我们通过do-while循环来判断,判断用的 compareAndSet 方法,本质是 CAS 语句。
  • 无等待

    • 无锁级别的改进。
    • 因为无锁级别并发只是要求一个线程可以在有限步内完成操作,而无等待要求所有的线程都必须在有限步内完成。
    • 无等待可以根据 do-while 循环次数来进一步分解为俩种无等待类型:
      • 有界无等待和线程数无关的无等待。
    • 应用:RCU结构(Read Copy Update)
      • 所有的读线程都是无等待的,也就是说它们既不会被锁定等待也不会引起任何冲突。
      • 写线程拥有原始数据的副本,接着只修改副本数据,修改完副本数据后会在合适的时机回写数据。

码云仓库同步笔记,可自取欢迎各位star指正:https://gitee.com/noblegasesgoo/notes

如果出错希望评论区大佬互相讨论指正,维护社区健康大家一起出一份力,不能有容忍错误知识。
										—————————————————————— 爱你们的 noblegasesgoo
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值