Java Concurrency In Practice

内容概要:《Java并发编程实战》


内容概要

  • 基础知识
    • 线程安全性
    • 对象的共享
    • 对象的组合
    • 基础构建模块
  • 结构化并发应用程序
    • 任务执行
    • 取消与关闭
    • 线程池
    • 图形界面应用程序
  • 活跃性, 性能与测试
    • 避免活跃性危险
    • 性能与可伸缩性
    • 并发程序的测试
  • 高级主题
    • 显式锁
    • 构建自定义同步工具
    • 原子变量与非阻塞同步工具
    • Java内存模型

1. 线程安全性

1.1 线程安全性

多个线程访问同一个可变的状态变量而没有使用同步,三种方式修复问题:

  • 不在线程之间共享该状态变量
  • 将状态变量修改为不可变的变量
  • 在访问状态变量时使用同步
    1.2 原子性
    1.3 加锁机制
    内置锁(synchronized):互斥锁,最多只有一个线程能够持有这种锁。因此,这个锁保护的同步代码块会以原子的方式执行。线程在进入代码块之前自动获得锁,并且在退出的时候自动释放锁,不论是正常退出,还是抛出异常而退出。
    重入(Reentrance): 重入意味着获取锁的操作的粒度是”线程”,而不是”调用”。

synchronized

  1. Java中每一个对象都可以作为锁,这是synchronized实现同步的基础:
  2. 普通同步方法,锁当前实例对象
  3. static同步方法,锁当前类的class对象
  4. 同步方法块,锁括号里面的对象
  5. 保证原子性,以及可见性
    1.4 活跃性与性能

2. 对象的共享

2.1 可见性(Memory Visibility)

synchronized关键字不仅能够保证原则性,同时还有另一个重要作用: 可见性。
我们希望确保当一个线程修改了对象状态后,其他线程能够看到发生的状态变化。
加锁的含义不仅仅局限于互斥行为,同时包括内存可见性。

因此,所有执行读操作或者写操作的线程都必须在同一个锁上同步。

volatile

  1. 一种稍弱的同步机制
  2. 内存屏障:编译器注意到volatile变量是共享的,因此不会将该变量的操作与其他内存操作一起重排序
  3. volatile不会被缓存在寄存器或者其他处理器不可见的地方
2.2 发布与逸出