深入理解Java虚拟机----(十)Java内存模型与线程

    Java虚拟机规范试图定义一种Java内存模型来消除不同硬件和操作系统的差异。JDK1.5(JSR-133)开始,Java内存模型终于算是开始完善起来。Java内存模型主要是目的是定义程序中可线程共享的变量的访问规则。它规定所有变量都存在主内存,每个线程有自己的工作内存,存储的是使用的变量的主内存拷贝。线程不能直接操作主内存中的变量,互相间也不能访问工作内存。交换、传输数据只能经过主内存。

内存间交互操作
    内存模型定义了8种操作: 
  • lock : 独占主内存变量
  • unlock
  • read : 主内存传输到工作内存
  • load : 主内存read的变量放到工作内存副本中
  • use : 工作内存中的变量传递给执行引擎
  • assign : 把执行引擎的一个赋值给工作内存中的变量
  • store : 工作内存变量传递到主内存
  • write : 把store的值写入主内存变量中
    8种操作必须满足以下8条规则:
  • read和load、store和write不能单一出现,即主内存中read了,工作线程必须load不能不接受。
  • 不允许丢弃最近的assign操作。即必须写回主内存
  • 不允许无原因的写回主内存
  • 新变量只能在主内存诞生
  • 一个变量同时只能被一个线程lock。可以lock多次,同等数量的unlock可以解除锁定。
  • 没lock的不能unlock。也不能unlock一个其他线程lock的变量
  • 对变量lock会清空工作线程中该变量副本,执行引擎使用钱需要重新load或assign初始化值。
  • unlock前必须写回主内存
    这8条规则加上以下对volatile的特殊规则,就定义了哪些操作是并发安全的。volatile有两个特性:
  • 保证此变量对所有线程的可见性,一个修改,其他的立即可见
  • 禁止指令重排。通过内存屏障实现。
    Java内存模型是围绕如何处理多线程环境下的原子性、可见性、有序性来建立的。
  • 原子性:8个操作都是原子的,可以认为基本数据类型的读写都是原子的。更大范围的需要,提供了lock和unlock,反映到Java代码就是synchronized。
  • 可见性:Java内存模型是通过变量修改后写回主内存,读取前从主内存刷新的方式保证可见性。volatile的规则就是保证了这两个操作的即时性。除了volatile还有两个可以实现,synchronized和final。
    • 同步块的可见性是通过上面的8条规则的倒数两条获得的。
    • final的可见性是通过“final字段在构造其中一旦初始化完成,并且构造器没有把final的引用传递出去,其他线程就能看到final字段的值”获得的。
  • 有序性:线程内看,操作是有序的;线程看另外一个线程,所有操作都是无序的(指的是指令重排、主内存和工作内存同步延迟)。Java提供volatile和synchronized保证有序性。volatile本身就禁止重排。synchronized则是由第五条规则获得的顺序能力,它使得一个同步块只能被线程串行的执行。

happens-before原则
    如果java内存模型所有的有序性都靠volatile和synchronized保证,有些操作将会很繁琐和困难。但是实际中,并没有感觉到,因为Java有一个happens-before原则。下面是Java内存模型中纯天然的默认happens-before关系,无需任何措施,就可以使用。可以作为推断两个操作会不会被打乱顺序的依据。
  • 单线程内有序
  • unlock操作happens-before后面对同一个锁的lock
  • Thread的start操作happens-before该线程的所有操作
  • 线程所有操作happens-before线程的终止监测
  • 线程的interrupt方法happens-before被中断线程的代码检测到中断的发生。
  • 对象的初始化完成happens-before它的finalize方法的开始
  • happens-before B 且 B happens-before C,则A happens-before C

Java线程
    线程实现有三种方式:
  • 轻量级线程:1对1模型,利用线程的调度功能。但开销大,需要内核态和用户态切换。
  • 用户线程:开销小,但是自己实现调度,管理复杂。1对多。
  • 混合:多对多。
    Java在windows和linux上都是一对一的模型。
    Java定义线程的五种状态:
  • 新建
  • 运行:正在执行或等待cpu分配时间
  • 无限期等待:不会被分配时间,只能等唤醒
    • 没有超时的wait
    • 没有超时的join
    • LockSupport.park()
  • 限期等待:
    • 有超时的wait、join
    • sleep
    • LockSupport.parkNanos()
    • LockSupport.parkUntil()
  • 阻塞:等待获得一个排他锁
  • 结束
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值