Java并发中的几个基本概念

原创
2018/02/11 16:26
阅读数 207

1. synchronized

  • synchronized方法的锁,就是该方法所在的对象本身
    • 静态synchronized方法从Class对象上获取锁
  • 每个Java对象都可以作为同步锁使用
    • 内置锁(intrinsic locks)
    • 监视器锁(monitor locks)
    • 互斥锁(mutual exclusion lock,Mutex)
    • 可重入(Reentrancy)
      • 持有锁的线程
      • 对应的计数器,请求计数器(acquisition count)
  • 临界区
  • 内存可见性
    • 重排序(reordering)
    • 过期数据
    • JVM 32 slot
      • 导致64位变量并发不安全
    • 同步
      • 线程A执行一个同步块时,线程B随后也进入同一个临界区
        • 则A在同步块之中/之前的操作,对B都是可见的

2. volatile

  • 同步的弱形式
  • 确保对一个变量的更新以可预见的方式告知其他的线程
  • 共享变量
  • 不会重排序
    • 不会缓存在寄存器
    • 不会缓存在处理器中
  • 读取时,总会返回某个线程所写入的最新值
  • 轻量级的同步机制
  • 不会引发线程阻塞
  • 不会加锁
  • 通常当作标志使用
    • 完成
    • 中断
    • 状态
  • 加锁可以保证
    • 可见性
    • 原子性
  • volatile
    • 可见性
  • 单写多读

3. 发布/逸出

  • 使数据/对象能够被当前范围之外的代码所使用,称为发布
  • 一个对象在尚未准备好时就发布出去,称为逸出
  • 间接发布
    • get方法直接返回引用
    • 内部类中this逸出(构造器中的this)
      • 构造器中将内部类发布出去
      • 使用内部final变量 + 工厂方法来避免
  • 对象初始化过程的同步
    • 变量的默认初始值
      • 相当于两次赋值
  • 安全发布
    • 通过静态初始化器初始化对象的引用
    • 将它的引用存储到volatile域或AtomicReference
    • 将它的引用存储到正确创建的对象的final域中
    • 将它的引用存储到由锁正确保护的域中

4. 线程封闭

  • 数据总是在同一个线程中被访问,就不需要任何同步
  • 如:Swing中的invokeLater机制
    • 在事件线程中安排执行Runnable
  • 池化
    • 资源在同一时间点,只能分配给一个线程使用
  • Ad-hoc 线程限制
    • 维护线程限制性的任务都由开发人员来实现
    • 易损性
    • 未经过设计而得到的线程封闭行为
  • 栈限制
    • 局部变量都在线程栈中
    • 其他线程无法访问
    • 引用的对象,还是需要额外的同步机制
  • ThreadLocal
    • 降低重用性
    • 不可滥用

5. 不可变性

  • 创建后状态不能被修改的对象,称为:不可变对象
  • 线程安全
  • 注意this逸出问题
  • final 域
    • 初始化安全性

6. 同步器(Synchronizer)

  • 用来调节相互协作的线程间的控制流
  • 同步容器
    • 早期JDK
      • Vector
      • Hashtable
      • Collections.synchronizedXxx 工厂方法
      • 使用自身作为锁(synchronized
        • 并发性弱
        • 锁竞争激烈
        • 吞吐量低
    • Iterator
      • 单线程中可在遍历过程中,对内容增减
      • 但多线程中,由于可见性等问题,仍然无法避免并发问题
        • 多线程场景中,即便使用Iterator,仍然需要考虑同步机制
    • fail-fast
      • ConcurrentModificationException
  • 并发容器
    • Queue
      • ConcurrentLinkedQueue
        • FIFO
      • PriorityQueue
        • 优先级
        • 非并发
    • BlockingQueue
      • 生产者-消费者
      • 异步
      • 解耦
      • 需要考虑:是否有界
        • 防止程序过载,耗尽内存
      • FIFO队列
        • LinkedBlockingQueue
        • ArrayBlockingQueue
      • 优先级队列
        • PriorityBlockingQueue
    • ConcurrentHashMap
      • 锁策略
        • 分段锁
        • 链表尾部加锁(Java 8)
      • 迭代器弱一致性
      • 无法客户端加锁
    • CopyOnWriteArrayList
      • 写时复制
      • 避免在迭代期间对容器加锁和复制
      • 不可变数据的线程安全特性
      • 复制带来额外开销
        • 数组复制
        • 数据量比较大时,性能开销大
  • 同步器队列
    • SynchronousQueue
      • 维护一个排队的线程清单
      • Blocking
      • 没有存储功能
  • Deque
    • BlockingDeque
    • 窃取工作
      • work-stealing
  • 同步器
    • 阻塞队列(BlockingQueue)
    • 闭锁(latch)
      • 阻塞一组线程,直到某些事件发生
      • CountDownLatch
      • FutureTask
        • 变相闭锁
        • 一旦进入完成状态,会永远停止在这个状态上
    • 信号量(semaphore)
      • 用来控制同时访问某特定资源的活动的数量
      • 管理着一个有效的许可(permit)集
      • 二元信号量
        • 计数初始值为:1
        • 变相的:互斥锁
          • 不可重入锁
    • 栅栏(barrier)
      • 阻塞一组线程,直到所有的线程到达
      • 闭锁等待事件,栅栏等待线程
      • CyclicBarrier
      • await会给每一个线程返回一个唯一的到达索引号
        • 可用于选举
      • Exchanger
        • 变相栅栏
    • 相位(phaser)

7. 任务(task)

  • 抽象、离散的工作单元
  • 清晰的任务边界(task boundaries)
    • 资源隔离
  • 独立性
    • 并不依赖于其他任务的状态、结果或者边界效应(side effect)
    • 独立有利于并发性
  • Runnable

8. Executor 框架

  • 管理两种资源
    • 任务
      • 类型
        • Runnable
        • Callable
      • 任务队列
        • BlockQueue
    • 线程
      • 线程工厂
      • 线程池
        • ThreadPoolExecutor
        • ScheduledThreadPoolExecutor
        • ForkJoinPool
  • 将任务与线程解耦
  • 提供统一地生命周期/回调
  • 执行策略
    • 任务在什么(++what++)线程中执行
    • 任务以什么(++what++)顺序执行(FIFO,LIFO,优先级)
    • 可以有多少个(++how many++)任务并发执行
    • 可以有多少个(++how many++)任务进入等待执行队列
    • 如果系统过载,需要放弃一个任务,应该挑选哪一个(++which++)任务
      • 如何(++how++)通知应用程序知道这一切
    • 在一个任务的执行前与结束后,应该做什么(++what++)处理
  • 生命周期
    • ExecutorService的3种状态
      • 运行(running)
      • 关闭(shutting down)
        • List<Runnable> shutdownNow()
        • boolean isShutdown()
        • boolean isTerminated()
        • boolean awaitTermination(long timeout, TimeUnit unit)
      • 终止(termination)
    • 任务
      • 创建
      • 提交
      • 开始
      • 完成
  • 拒绝执行处理器
    • java.util.concurrent.RejectedExecutionHandler
  • 周期性任务
    • ScheduledThreadPoolExecutor
  • 异步任务处理
    • java.util.concurrent.ExecutorCompletionService<V>
  • 任务队列
    • 无限队列
      • ArrayBlockingQueue
      • LinkedBlockingQueue
      • PriorityBlockingQueue
    • 有限队列
    • 同步移交
  • 饱和策略

9. 中断

  • 处理可取消
    • 用户请求取消
    • 限时活动
    • 应用程序事件
    • 错误
    • 关闭
  • 没有绝对安全的停止线程的方法
  • 相互协作的机制
  • 大循环/关键步骤的重要检查点:线程是否中断
  • api
    • public boolean isInterrupted()
    • public void interrupt()
    • public static boolean interrupted()
  • 中断策略
    • 最有意义的是对线程级(thread-level)和服务级(service level)取消的规定
      • 尽可能迅速退出
      • 如需清理,尽可能通知相关实体
      • 此线程已经退出
    • 区分任务线程对中断的反应
  • 通过Future取消任务
  • 通过致命药丸关闭线程
    • 无界队列
  • 显式Lock提供lockInterruptibly在锁等待时,还能响应中断
  • 定制newTaskFor方法,来封装非标准的取消动作

10. 异常

  • UncaughtExeceptionHandler
展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
18 收藏
0
分享
返回顶部
顶部