Skip to content

zhyyu/learn-concurrency

Repository files navigation

并发编程学习总结

1 线程安全性

1.1 什么是线程安全

多个线程访问某个类时, 不管运行时环境采用何种调度方式或者这些线程将如何交替执行, 并且在主调代码需要任何额外的同步或协同, 这个类都能表现出正确的行为, 那么就称这个类是线程安全

1.2 竞态条件(Race Condition)

当某个计算的正确性取决于多个线程的交替执行时, 那么就会发生竞态条件. 换句话说, 就是正确的结果要取决于运气. 最常见的竞态条件就是"先检查后执行(Check-Then-Act)"操作, 即通过一个可能失效的观测结果来决定下一步的动作.

1.3 原子/原子操作

假定有两个操作A 和B, 如果从执行A 的线程来看, 当另一个线程执行B 时, 要么将B 全部执行完, 要么完全不执行B, 那么A 和B 对彼此来说就是原子的. 原子操作是指, 对于访问同一个状态的所有操作(包括该操作本身)来说, 这个操作是一个以原子方式执行的操作.

1.4 内置锁
  • 独占性
  • 可见性(经常被忽略)
    • volatile
    • image
1.5 用锁来保护状态

对于可能被多个线程同时访问的可变状态变量, 在访问它时都需要持有同一个锁, 在这种情况下, 我们称状态变量是由这个锁保护的.

  • 多个状态变量下反例
    • image
1.6 可见性
  • 非线程安全的可变整数类
    • image
  • 线程安全的可变整数类
    • image
1.7 volatile(保证可见性不保证原子性)
  • 当且仅当满足以下所有条件时, 才应当使用volatile 变量(java 运算符对应多条jvm 指令)
    • 对变量的写入操作不依赖变量的当前值, 或者你能确保只有单个线程更新变量的值
    • 该变量不会与其他状态变量一并纳入不变性条件
    • 在访问变量时不需要加锁
1.8 线程封闭(Thread Confinement)

当某个对象封闭一个线程中是, 这种用法将自动实现线程安全性, 即使被封闭的对象本身不是线程安全的.

  • ThreadLocal
  • 动态数据源
  • MDC
1.9 安全发布
  • 不安全发布
    • image
  • 安全发布的常用模式
    • 在静态初始化函数中初始化一个对象引用
    • 将对象引用保存到volatile 类型的域或者AtomicReference 对象中
    • 将对象引用保存到某个正确构造对象的final 类型域中
    • 将对象引用保存到一个由锁保护的域中

2 jdk concurrent util

2.1 并发容器
  • ConcurrentHashMap
    • ConcurrentModificationException
    • image
    • image
    • image
  • CopyOnWriteArrayList
    • 在每次修改时, 都会创建并重新发布一个新的容器副本
    • 仅当迭代操作远远多于修改操作时, 才应该使用
  • CopyOnWriteArraySet
2.2 阻塞队列
  • LinkedBlockingQueue
  • ArrayBlockingQueue
2.3 同步工具类
  • CountDownLatch
    • image
  • FutureTask
    • image
  • Semaphore
    • image
  • CyclicBarrier
    • image
    • image

3 Executor

3.1 为何要使用Executor
  • 简单web 服务器的几种方式
    • image
    • image
    • image
  • ThreadPool vs NewThread
    • image
    • image
3.2 Executor 详细配置
  • 静态工厂方法
    • newFixedThreadPool
    • newCachedThreadPool
    • newSingleTHreadExecutor
    • newScheduledThreadPool
  • 生命周期
    • 使用ExecutorService 后会存在一非守护线程, 若不手动结束, 则JVM 不会退出
    • image
    • image
  • 设置线程池大小
    • image
    • image
    • Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
  • 工作队列 ArrayBlockingQueue & LinkedBlockingQueue & SynchronousQueue
    • image
    • image
    • image
    • image
  • submit 源码分析
    • image
    • image
    • image
    • image
  • 饱和策略
    • 默认策略(AbortPolicy)
      • image
      • image
      • image
    • AbortPolicy
      • image
    • CallerRunsPolicy
      • image
      • image
    • DiscardPolicy
      • image
    • DiscardOldestPolicy
      • image
  • 自定义线程工厂
    • image
    • image
3.3 Executor 注意事项
  • compatible with ThreadLocal
    • image
    • image

4 取消与关闭

4.1 已请求取消
  • 标志位
    • image
    • image
4.2 中断方法
  • api
    • image
  • InterruptException
    • image
    • image
    • image
4.3 通过Future 来实现取消
  • 通过Future 来取消任务
    • image
    • image
    • image
    • image
4.4 处理非正常的线程终止
  • UncaughtExceptionHandler
    • image
    • image
    • image
4.5 JVM 关闭
  • 守护线程
    • image
  • 关闭钩子
    • image

5 性能

5.1 减少锁的竞争
  • 缩小锁的范围
    • image
    • image
  • 减小锁的粒度
    • image
    • image
  • 锁分段
    • ConcurrentHashMap
    • image

6 显示锁

6.1 ReentrantLock
  • lock
    • image
  • tryLock
    • image
  • tryLock(within time)
    • image
  • lockInterruptibly
    • image
6.2 ReentrantReadWriteLock
  • 使用场景
    • image
  • 锁降级
    • image
    • image

7 条件队列

7.1 条件队列解决问题
  • image

"条件队列"这个名字来源于: 它使得一组线程(称之为等待线程集合)能够通过某种方式来等待特定的条件变成真

  • 为何要使用条件队列
    • image
    • image
    • image
    • image
7.2 wait/notify/notifyAll
  • wait
    • image
    • image
  • notify/nofityAll
    • image
    • image
7.3 如何使用条件队列
  • 条件谓词

    条件谓词是使某个操作成为状态依赖的前提条件. 在有界缓存中, 只有当缓存不为空时, take 方法才能执行, 否则必须等待. 对take 方法来说, 它的条件条件谓词就是"缓存不为空"

  • 过早唤醒

    • nofityAll 时, 条件维持为真, 等到线程获取monitor 时, 条件为假
    • notifyAll 时, 条件为假, 如BoundedBuffer "非满" "非空" 条件谓词共用一个条件队列
    • image
  • 通知

    每当在等待一个条件时, 一定要确保在条件谓词变为真时, 通过某种方式发出通知

    • 若多个条件谓词等待同一条件队列, 则使用nofifyAll 而非notify, 否则容易产生信号丢失问题
7.4 Condition
  • 为何要使用
    • BoundedBuffer, 两个条件谓词均使用同一条件队列, 使用notifyAll, 造成性能损耗
    • 便于分析, 不同条件谓词对应不同条件队列, 对应不同signal 入口
  • 与内置条件队列区别
    • image
  • ArrayBlockingQueue 源码
    • image
    • image
    • image
    • image
    • image
  • LinkedBlockingQueue 源码
    • image
    • image
    • image
    • image
7.5 AbstractQueuedSynchronizer(AQS)
  • 为何使用
    • 处理大量细节, 等待线程采用FIFO 队列操作顺序
    • lock, condition 两时刻阻塞; AQS 一时刻阻塞
  • AbstractQueuedSynchronizer
    • image
    • image
    • image
  • CountDownLatch
    • image
    • image
    • image
    • image
    • image
    • image
    • image
    • image
    • image

8 Java 内存模型

  • 重排序
    • image
  • 不安全发布
    • image
  • 安全的发布
    • image
    • image
  • 初始化过程的安全性
    • 初始化安全性将确保, 对于被正确构造的对象, 所有线程都能看到由构造函数为对象各个final 域设置的正确值, 而不管采用何种方式来发布对象

    • image


相关资源

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages