博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
对于同步的规则定义
阅读量:3929 次
发布时间:2019-05-23

本文共 1588 字,大约阅读时间需要 5 分钟。

线程间操作的定义

  1. 线程间操作指:一个程序执行的操作可被其他线程感知或被其他线程直接影响
  2. Java内存模型只描述线程间操作,不描述线程内操作,线程内操作按照线程内语义执行。

线程间操作有:

  • read操作(一般读,即 非volatile读)
  • write操作(一般写,即 非volatile写)
  • volatile read
  • volatile write
  • Lock.(锁monitor)、Unlock
  • 线程的第一个和最后一个操作
  • 外部操作

所有线程间操作,都存在可见性问题,JMM需要对其进行规范

volatile关键字

可见性问题:让一个线程对共享变量的修改,能够及时的被其他线程看到。 Java内存模型规定:对volatile变量v的写入,与所有其他线程后续对v的读同步。

要满足这些条件,所以volatile关键字就有这些功能:

  1. 禁止缓存:

volatile变量的访问控制符会加个

  • ACC_VOLATILE——https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5
  1. 对volatile变量相关的指令不做重排序。

double和long的特殊处理

由于《Java语言规范》的原因,对非volatile的double、long的单次写操作是分两次来进行的,每次操作其中32位,这可能导致第一次写入后,读取的值是脏数据,第二次写完成后,才能读到正确值。

在这里插入图片描述

  • 读写volatile修饰的long、double是原子性的。
  • 商业JVM不会存在这个问题,虽然规范没要求实现原子性,但是考虑到实际应用,大部分都实现了原子性。
  • 《Java语言规范》中说道: 建议程序员将共享的64位值(long、double)用volatile修饰或正确同步其程序以避免可能的复杂情况。

对于同步的规则定义

  • volatile变量v的写入,与所有其他线程后续对v的读同步

  • 对于监视器m的解锁与所有后续操作对于m的加锁同步。

    在这里插入图片描述

  • 对于每个属性写入默认值(0,false,null)与每个线程对其进行的操作同步。

    在这里插入图片描述

  • 启动线程的操作与线程中的第一个操作同步。

    在这里插入图片描述

  • 线程T2的最后操作与线程T1 发现线程T2已经结束同步。(isAlive,join可以判断线程是否终结)

    在这里插入图片描述

  • 如果线程T1中断了T2,那么线程T1的中断操作与其他所有线程发现T2被中断了同步。通过抛出InterruptedException异常,或者调用Thread.interruptedThread.isInterrupted

    在这里插入图片描述

Happens-before现行发生原则

happens-before 关系用于描述两个有冲突的动作之间的顺序,如果一个action happens before 另一个action,则第一个操作被第二个操作可见,JVM需要实现如下happens-before规则:

  • 某个线程中的每个动作都happens-before 该线程中该动作后面的动作。
  • 某个管程上的unlock 动作 happens-before 同一个管程上后续的 lock 动作。
  • 对某个 volatile 字段的写操作 happens-before 每个后续对该volatile字段的读操作。
  • 在某个线程对象上调用start()方法 happens-before被启动线程中的任意动作。
  • 如果在线程t1中成功执行了t2.join(),则t2中的所有操作对t1可见。
  • 如果某个动作 A happens-before 动作 B,且B happens-before 动作C,则有 A happens-before C。

当程序中包含两个没有被 happens-before 关系排序的冲突访问时,就称存在数据竞争遵守了这个原则,也就意味着有些代码不能进行重排序,有些数据不能缓存!

转载地址:http://emugn.baihongyu.com/

你可能感兴趣的文章
SpringMVC 过滤器Filter使用解析
查看>>
SpringMVC中使用Interceptor拦截器
查看>>
send email Java发送邮件
查看>>
Java mail 邮箱发送
查看>>
spring有三种启动方式
查看>>
大型电子商务网站架构
查看>>
小型电子商务网站设计原则
查看>>
大型Java多用户商城系统设计开发的心得和困难
查看>>
CGLib与JDK的动态代理
查看>>
Java单元测试(Junit+Mock+代码覆盖率)
查看>>
怎样使用 Junit Framework 进行单元测试的编写
查看>>
MAVEN常用命令+基本配置详解 2015
查看>>
java:快速文件分割及合并
查看>>
redis 学习笔记(1)-编译、启动、停止
查看>>
redis 学习笔记(2)-client端示例代码
查看>>
redis 学习笔记(3)-master/slave(主/从模式)
查看>>
redis 学习笔记(4)-HA高可用方案Sentinel配置
查看>>
redis 学习笔记(5)-Spring与Jedis的集成
查看>>
nginx学习(1):编译、安装、启动
查看>>
nginx学习(2):启动gzip、虚拟主机、请求转发、负载均衡
查看>>