chapter21 Java多线程编程在Netty中的应用

chapter21 Java多线程编程在Netty中的应用

1. Java内存模型与多线程编程

1.1 Java内存模型

  • JVM规范定义了Java内存模型,来屏蔽各种操作系统、虚拟机实现厂商和硬件的内存访问差异。
    1. 工作内存和主内存
      • 所有变量都存储在主内存中,每个线程都有自己独立的工作内存,它保存了该线程使用的变量的主内存的复制。线程间的变量访问需要通过主内存来完成。
    2. Java内存交互协议
      • 定义了8种操作来完成主内存和工作内存的变量访问
      • lock: 主内存变量,把一个变量标识为某个线程独占的状态。
      • unlock:主内存变量,把一个处于锁定的变量释放出来
      • read:主内存变量,把一个变量的值从主内存传输到线程的工作内存中,以便随后的load操作使用
      • load:工作内存变量,把read读取到的主内存中的变量值放入到工作内存的变量副本中
      • use:工作内存变量,把工作内存变量的值传递给java虚拟机执行引擎,每当虚拟机遇到一个需要使用到变量值的字节码指令时,将会执行该操作
      • assign:工作内存变量,把从执行引擎接收到的变量的值赋给工作变量,每当虚拟机遇到一个变量赋值的字节码指令时,将会执行该操作
      • store:工作内存变量,把工作内存中的一个变量的值传送到主内存中,以便随后的write操作使用
      • write:主内存变量,把store操作从工作内存中的变量值放入主内存的变量中
    3. Java的线程
      • 目前操作系统实现线程的方式主要有三种:【sun的jdk,在windows和linux上采用内核线程的实现方式】
      • 内核线程(KLT)实现:有内核来完成线程切换,并负责将线程任务映射到不同的处理器上
      • 用户线程实现(UT):用户线程是指完全建立在用户空间线程库上的线程,用户线程的创建、启动、运行、销毁和切换完全在用户态中完成,不需要内核帮助,因此性能更高
      • 混合实现:将内核线程和用户线程混合在一起使用的方式

2、Netty的并发编程实线

2.1 对共享的可变数据进行正确同步

2.2 正确使用锁

  • wait方法使线程等待某个条件,它必须在同步块内部被调用,这个同步块通常会锁定当前对象实例。
  • 始终使用wait循环来调用wait方法,永远不要在循环之外调用wait方法。
  • 唤醒线程,保守使用notifyAll,当处于等待的所有线程都在等待同一个条件,而每次只有一个线程可以从这个条件中被唤醒,那么就用notify

2.3 volatile的正确使用

  • volatile时java提供的最轻量级的同步机制,Java内存模型对volatile专门定了一个特殊的访问规则,仅仅解决了可见性的问题
  • 线程可见性
  • 禁止指令重排序优化
  • volatile最适合使用的是一个线程写,其他线程读的场合。

2.4 CAS指令和原子类

2.5 线程安全类的应用

  • 线程池
  • 并发集合
  • 新的同步器
  • 新的原子包装类

2.6 读写锁的应用

  • ReadWriteLock使用场景:
    1. 读多写少
    2. 读写锁是可重入、可降级的,一个线程获取读写锁后,可以继续递归获取;从写锁可以降级为读锁,以便快速释放锁资源
    3. ReentrantReadWriteLock支持获取锁的公平策略
    4. 读写锁支持非阻塞的尝试获取锁,如果获取失败,直接返回false,而不是阻塞
    5. 获取锁之后一定要释放锁,否则会发生锁溢出异常。

2.7 线程安全性文档说明

2.8 不要依赖线程优先级

  • Netty默认的线程工厂提供了实现类,开发了包含设置线程优先级字段的构造函数,这是个错误的决定。实际上JDK的优先级是无法跨平台正确运行的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章