《深入理解Java虚拟机》读书笔记---Java内存模型与线程

12.1概述

计算机CPU的运算速度远大于通信子系统的速度,计算机同时做多件事情。

12.2 硬件效率&一致性

处理器私有高速缓存,共享主内存,存储设备的速度远小于处理器运算速度,因而需要缓存。缓存数据读取自主内存中,缓存–主内存===数据一致性。

12.3.1主内存&工作内存

Java 内存模型主要目标是定义程序中各个变量的访问规则。变量包含 —实例字段、静态字段、构成数组对象的元素,但不包含局部变量、方法参数。前者是数据存储在堆中,后者存储栈中,栈属于线程私有数据。

线程有自己的工作内存,工作内存中的变量来自主内存。线程间变量的传递需要通过主内存来完成。
工作内存 < == > 主内存 < == >工作内存
线程通过load & save 来与主内存交互

12.3.2内存交互操作
  • JVM有8种原子性内存交互操作
  • lock:作用主内存,线程独占状态。
  • unlock:作用主内存,变量被释放。
  • read:作用主内存,从主内存传输到工作内存
  • load:作用工作内存变量,从主内存读到的变量值放入工作内存变量副本中。
  • use:作用工作内存变量,把工作内存变量的值传递给执行引擎。
  • assign:作用工作内存变量,把执行引擎的值赋值给工作内存的变量
  • store:工作内存的变量值传递到主内存。
  • write;把store操作中得到的值放入到主内存的变量中。
    read->load;store->write 顺序执行,但非连续执行。
    工作内存中的assign会同步到主内存。同一个变量可以被单个线程多次Lock,同时要进行相应次数的unlock.

等效判断原则----先行发生原则。

12.3.3 volatile关键字

volatile变量

  1. 对所有线程可见,修改后的值对于其他线程是立即可知的。
  2. volatile变量所有写操作都能立即反应到其它线程。
  3. volatile禁止指令重排序
    Java运算并非原子操作

2019.5.18 星期六


12.3.5 原子,可见,有序

java内存模型保证原子性操作–read,load, assign,use,store,write.

可见性:一个线程修改了共享变量,其他线程能够立即得知–通过主内存媒介来交换。volatile的特殊之处在于新值能立即同步到主内存,每次使用前立即从主内存中刷新。java 还有synchronized,final两个关键字能保证变量可见性。

有序性:线程内表现为串行执行,指令重排序,工作内存与主内存同步延迟。在本线程内观察,所有操作都是有序的;在一个线程中观察另一个线程,所有操作都是无序的。

先行发生原则

前操作的影响能被后操作观察到。

  • 程序次序规则
  • 管程锁定规则
  • volatile变量规则:写操作先行发生于读操作
  • 线程启动规则:start方法先行发生于此线程每个操作。
  • 线程终止原则
  • 线程中断规则
  • 对象终结规则:finalize()方法在构造方法后面执行。
  • 传递性:A先于B,B先于C,那么A先于C
12.4 java与线程

并发不一定要依赖多线程。

12.4.1 线程实现

java语言跨平台,线程实现依赖平台实现。线程是比进程更轻量级的调度执行单位。线程引入,把一个进程的资源与执行调度分开。线程是cpu调度的基本单位。

  1. 使用内核实现
    内核线程KLT,有操作系统内核支持的线程,内核完成线程的切换,操纵调度器对线程调度,线程任务映射到处理器。
    内核线程的高级接口–轻量级进程LWP即线程。
    系统调用代价相对较高。主要有如下问题:
    A.用户态&内核态来回切换
    B.轻量级进程消耗内核资源

  2. 用户线程
    线程的建立、同步、销毁和调度完全在用户态中完成,不需要内核协助
    进程 1 ---- 用户线程 n
    缺点:用户线程实现复杂。

  3. UT + LWP混合实现
    使用内核的线程调度、处理器映射,UT调度通过轻量级进程来实现。

  4. java线程实现
    java线程基于平台。linux系统中,一条java线程映射到一条轻量级线程。

12.4.2 JAVA线程调度

线程调度是指系统为线程分配处理器使用全的过程。协同式调度、抢占式调度。
抢占式:系统来分配执行时间。

12.4.3 线程状态转换

5种线程状态:

  • 新建
  • 运行
  • 等待 无限期等待、限期等待。
  • 阻塞
  • 结束
13 线程安全与锁优化

13.2 线程安全

当多个线程访问一个对象时,如果不考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步操作,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那么这个对象是线程安全的。

对象的安全性:代码封装所有必要的正确性保障手段。

13.2.1 java语言中的线程安全

Java线程安全并非是一个非真即假的问题,它有5中类型:

  1. 不可变,final 修饰,值不可变,枚举,Long,Double,BigInteger,BigDecimal.
  2. 绝对线程安全,Vector,线程安全方法被synchronized修饰。
  3. 相对线程安全,在调用端需要额外的同步手段
  4. 线程兼容
  5. 线程对立,无论调用端是否采用同步措施,都无法在多线程中并发使用的代码。例如Thread suspendresume方法。
13.2.2 线程安全实现方法
  1. 互斥同步
    多个线程访问共享数据时,只有一个线程使用。临界区、互斥量、信号量。
    互斥是方法,同步是目的,同步不一定需要互斥。
    synchronized,重入锁ReentrantLock.
    可重入锁有3个特性:等待可中断,实现公平锁、锁可以绑定多个条件。
  2. 非阻塞同步
    可重入代码;线程本地存储;消费队列架构模式;web交互模型(一个请求对应一个服务器线程);线程数据独立。
    硬件指令集支持–比较交换:先进行运算,如果原值未发生改变,则此次操作成功。这个是一个原子操作。
  3. 无同步方案
    可重入代码,数据都不共享。ThreadLocal
13.3 锁优化
13.3.1 自旋锁&自适应自旋

基于一个现象:共享数据的锁定状态只会持续很短的时间。JVM已经默认开启。
自适应锁,自适应自旋时间不固定,由JVM来决定。

13.3.2 锁消除

对不可能存在共享数据竞争的锁进行消除。

13.3.3 锁粗化

是为了解决反复枷锁、解锁操作。

13.3.4 轻量级锁

在没有多线程竞争的前提下,减少传统锁的使用

偏向锁

把整个同步都消除掉

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值