Java 并发编程 回忆提纲、总结

参考资料:《Java并发编程的艺术》

用于快速回忆,详情请看书籍原文

1. 一些概念

1.1 上下文切换

  • 定义:任务从保存到再加载的过程
  • 减少上下文切换
    • 无锁并发编程:将临界资源划分给不同线程各自访问
    • CAS算法
    • 最少线程原则:不创建无用的线程
    • 协程:在单线程里面实现多任务调度(IO多路复用)

1.2 死锁

  • 死锁:两个或两个以上的线程在执行过程中,由于竞争临界资源或者而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去
  • 减少死锁的发生
    • 避免一个线程同时获取多个锁
    • 避免线程在锁内占用过多的资源
    • 使用定时锁(超时直接返回)
    • 对于数据库锁,加锁与解锁必须在同一个数据库连接中

1.3 资源限制

  • 资源限制:程序的执行速度受限于计算机软硬件资源
  • 缓解资源限制
    • 硬件资源限制:集群
    • 软件资源限制:复用资源(连接池)

2. 并发机制的底层实现原理

2.1 volatile

  • 原理:volatile变量写操作汇编之后会插入Lock指令

    • 将当前处理器缓存行的数据写回主存
    • 使在其它CPU里缓存了该内存地址的数据无效(遵守缓存一致性协议,嗅探)

2.2 synchronized

  • Java一切对象都可以作为锁

    • 普通同步方法:锁是当前实例对象
    • 静态同步方法:锁是当前类的Class对象
    • 同步代码块:锁是synchronized括号中配置的对象
  • 对象头 Mark Word
    • hash code
    • 分代年龄
    • 锁标记
  • 锁的种类
    • 偏向锁
    • 轻量级锁
    • 重量级锁

2.3 原子操作的实现原理

  • 处理器实现

    • 总线锁
    • 缓存锁定
  • Java实现
    • 循环CAS
  • CAS的问题
    • ABA问题
    • 循环时间长开销大
    • 只能保证一个共享变量的原子性

3. 内存模型

3.1 内存模型基础

  • 通信机制 (Java采用共享内存)

    • 消息传递 通信方式:消息传递,显式通信;隐式同步
    • 共享内存 通信方式:共享内存,隐式通信;显式同步
  • JMM:决定一个线程对共享变量的写入何时对其它线程可见

3.2 重排序

  • 定义:编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段

    • 编译器级别:编译器优化(JMM禁止部分)
    • 指令级别:指令级并行技术(ILP)(内存屏障)
    • 内存系统级别:由于写缓存的存在,使得加载域储存可能乱序(内存屏障)
  • 内存屏障的类型
  • 数据依赖性:两个操作同时访问一个共享变量,且有至少一个操作为写操作
  • as-if-serial语义
  • 程序顺序规则

3.3 顺序一致性

  • 顺序一致性内存模型:单刀多路开关
  • JMM保证如果程序是正确同步的,其执行将具有顺序一致性

3.4 volatile的内存语义

  • 特性:可见性,原子性
  • volatile的读写与锁的释放获取有相同的内存语义(建立了一种happen before原则)
    • 写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量刷新到主存
    • 读一个volatile变量时,JMM会把该线程对应的本地内存置为无效,线程会从主存中读取最新值
  • volatile内存语义的实现:内存屏障

3.5 锁的内存语义

3.6 final域的内存语义

3.7 happen before 原则

  • 程序顺序原则
  • 监视器锁原则
  • volatile变量原则
  • 传递性原则
  • start()规则
  • join()规则

3.8 双重检查锁定以及延迟初始化

  • 双重检查锁定实现单例模式在多线程环境下由于重排序导致可能出现错误

    • volatile
    • 静态内部类

4. 并发编程基础

4.1 线程

  • 轻量级进程LWP
  • 线程优先级
  • 线程状态转移

4.2 启动与终止线程

  • 构造
  • 启动
  • 中断安全地终止线程
    • 中断
    • volatile标记

4.3 线程间通信

  • volatile、synchronized
  • 等待通知机制
  • 管道流:传输媒介为主存
  • join方法
  • ThreadLocal 线程变量

5. 锁

5.1 Lock接口

5.2 队列同步器

  • 使用
  • 实现

5.3 重入锁 ReentrantLock

  • 重入
  • 公平

5.4 读写锁

维护了一对锁:读锁与写锁

  • 实现

    • 通过分割比特位,实现利用int类型变量维护同步状态

5.5 LockSupport

阻塞或者唤醒一个线程

5.6 Condition接口

与Lock搭配实现通知/等待模式

6. 并发容器与框架

6.1 ConcurrentHashMap

分段锁

6.2 ConcurrentLinkedQueue

基于链接节点的无界线程安全队列

6.3 阻塞队列

  • ArrayBlockingQueue
  • LinkedBlockingQueue
  • PriorityBlockingQueue
  • DelayQueue
  • SynchronousQueue
  • LinkedTransferQueue
  • LinkedBlockingDeque

6.4 Fork/join框架

工作窃取算法

7. 原子操作类

7.1 原子更新基本类型

7.2 原子更新数组

7.3 原子更新引用类型

7.4 原子更新字段

8. 并发工具类

8.1 CountDownLatch

8.2 CyclicBarrier

8.3 Semaphore

8.4 Exchanger

9. 线程池

9.1 原理

9.2 使用

  • 创建
  • 提交
  • 关闭

10. Executor框架

10.1 简介

  • 两级调度模型:Java线程与系统线程一一对应。由Executor将用户的任务分配给各个线程,一个线程可能对应着多个任务
  • Executor框架架构
    • 任务:Runnable、Callable接口
    • 任务执行者:继承自Executor接口的ExecutorService接口,以及其两个实现类ThreadPoolExecutor、ScheduledThreadPoolExecutor(ThreadPoolExecutor,ScheduledThreadPoolExecutor又可以分化成5个常用的ThreadPool,但是实际上并不存在这5种类型,只是调用了各自的构造函数并传入了不同的参数)
    • 异步计算的结果:Future接口以及FutureTask实现类

10.2 ThreadPoolExecutor

  • FixedThreadPool 固定线程数量

    • LinkedBlockingQueue
  • SingleThreadPool 单线程
    • LinkedBlockingQueue
  • CachedThreadPool 按需创建线程
    • SynchronousQueue 传递式

10.3 ScheduledThreadPoolExecutor

在给定时延之后执行任务,功能与Timer类似但是更为强大

  • ScheduledThreadPool 多线程
  • SingleScheduledThreadPool 单线程
  • ScheduledFutureTask DelayQueue(封装了PriorityQueue,执行时间短的优先执行)

10.4 FutureTask

  • FutureTask不仅实现了Future接口,还实现了Runnable接口
  • 基于AQS实现

原文地址:https://www.cnblogs.com/Libinkai/p/12305520.html

时间: 2024-10-03 01:15:53

Java 并发编程 回忆提纲、总结的相关文章

Java并发编程:Concurrent锁机制解析

.title { text-align: center } .todo { font-family: monospace; color: red } .done { color: green } .tag { background-color: #eee; font-family: monospace; padding: 2px; font-size: 80%; font-weight: normal } .timestamp { color: #bebebe } .timestamp-kwd

Java并发编程:Callable、Future和FutureTask(转)

Java并发编程:Callable.Future和FutureTask 在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需要获取执行结果,就必须通过共享变量或者使用线程通信的方式来达到效果,这样使用起来就比较麻烦. 而自从Java 1.5开始,就提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果. 今天我们就来讨论一下Callabl

Java并发编程 Volatile关键字解析

volatile关键字的两层语义 一旦一个共享变量(类的成员变量.类的静态成员变量)被volatile修饰之后,那么就具备了两层语义: 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的. 2)禁止进行指令重排序. 根据volatile的语义,我们可以看到,volatile主要针对的是并发三要素(原子性,可见性和有序性)中的后两者有实际优化作用. 可见性: 线程本身并不直接与主内存进行数据的交互,而是通过线程的工作内存来完成相应的操作.

Java并发编程

synchronized是Java中的关键字,在并发编程中被称为内置锁或者监视器锁.当用它来修饰一个方法或者一个代码块的时候能够保证同一时刻最多只有一个线程执行该段代码. Java的内置锁相当于一种互斥锁,最多只有一个线程能够持有这种锁,故而由这个锁保护的同步代码块会以原子方式执行,多个线程在执行该代码时就不会相互干扰. 但由于被锁保护的同步块代码是以串行形式来访问的,即多个线程以独占的方式访问对象,而这也导致如果被锁保护的同步代码块的作用范围过大,会导致并发不良. 这里有必要简单讲一下内置锁的

6、Java并发编程:volatile关键字解析

Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以重获生机. volatile关键字虽然从字面上理解起来比较简单,但是要用好不是一件容易的事情.由于volatile关键字是与Java的内存模型有关的,因此在讲述volatile关键之前,我们先来了解一下与内存模型相关的概念和知识,然后分析了volatil

7、Java并发编程:深入剖析ThreadLocal

Java并发编程:深入剖析ThreadLocal 想必很多朋友对ThreadLocal并不陌生,今天我们就来一起探讨下ThreadLocal的使用方法和实现原理.首先,本文先谈一下对ThreadLocal的理解,然后根据ThreadLocal类的源码分析了其实现原理和使用需要注意的地方,最后给出了两个应用场景. 以下是本文目录大纲: 一.对ThreadLocal的理解 二.深入解析ThreadLocal类 三.ThreadLocal的应用场景 若有不正之处请多多谅解,并欢迎批评指正. 请尊重作者

java并发编程实战学习(3)--基础构建模块

转自:java并发编程实战 5.3阻塞队列和生产者-消费者模式 BlockingQueue阻塞队列提供可阻塞的put和take方法,以及支持定时的offer和poll方法.如果队列已经满了,那么put方法将阻塞直到空间可用:如果队列为空,那么take方法将阻塞直到有元素可用.队列可以是有界的也可以是无界的. 如果生产者生成工作的速率比消费者处理工作的速率款,那么工作项会在队列中累计起来,最终好紧内存.同样,put方法的阻塞特性也极大地简化了生产者的编码.如果使用有界队列,当队列充满时,生产者将阻

Java 并发编程之任务取消(九)

Jvm关闭 jvm可正常关闭也可强行关闭,正常关闭有多种触发方式: 当最后一个正常(非守护,下面会讲到什么是守护线程)线程结束时 当调用system.exit时,或者通过其他特定于平台的方法关闭时(例如发送了SIGINT信号或键入Ctrl-c) 通过其他特定平台的方法关闭jvm,调用Runtime.halt或者在操作系统当中杀死JVM进程(例如发送sigkill)来强行关闭jvm. 关闭钩子 在正常关闭中,jvm首先调用所有已注册的关闭钩子,关闭钩子是指通过 Runtime.addShutdow

Java并发编程笔记 并发概览

并发概览 >>同步 如何同步多个线程对共享资源的访问是多线程编程中最基本的问题之一.当多个线程并发访问共享数据时会出现数据处于计算中间状态或者不一致的问题,从而影响到程序的正确运行.我们通常把这种情况叫做竞争条件(race condition),把并发访问共享数据的代码叫做关键区域(critical section).同步就是使得多个线程顺序进入关键区域从而避免竞争条件的发生. >>线程安全性 编写线程安全的代码的核心是要对状态访问操作进行管理,尤其是对共享的和可变的状态访问. 线