4.2.1 java线程安全之可见性

JVM运行时数据区

在这里插入图片描述

Java内存模型(Java Memory Model ,JMM) VS JVM运行时数据区

在这里插入图片描述

初看Java内存模型

在这里插入图片描述

多线程中的问题

  1. 所见非所得
  2. 无法肉眼去检测程序的准确性
  3. 不同的运行平台有不同的表现
  4. 错误很难重现
    eg 问题:(t1总的线程会一直执行下去为什么呢?jit对这种频繁调用的代码做了优化 会先取demo1.flag 赋值给一个局部变量 然后去判断这个局部变量的值 后面又详细的图)
    在这里插入图片描述在这里插入图片描述

工作内存缓存

在这里插入图片描述

CPU指令重排

在这里插入图片描述

JIT编译器(Just in time compiler)

脚本语言与编译语言的区别?
解释执行:即咱们说的脚本,在执行时,由语言的解释器将其一条条翻译成机器可识别的指令
编译执行:将我们写的程序,直接编译成机器可以识别的代码。
java是什么语言:
在这里插入图片描述
在这里插入图片描述

volatile关键字

可见性问题:让一个线程对共享变量的修改,能够及时的被其他线程看到
java内存模型规定:对volatile变量v的写入,与所有其他线程后续对v的读同步
要满足这些条件,所以volatile关键字就有这些功能:

  1. 禁止缓存
    volatile变量的访问控制符会加个ACC_VOLATILE—可以用javap -p -v aa,class进行查看
    https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.5
  2. 对volatile变量相关的指令不做重排序
public class VisibilityDemo {
    // 运行标志
//    public volatile boolean flag = true;
    /*
     *不带volatitle的时候thread1不会停止  jit 做了优化对于循环取值的时候
     * boolean aa=demo1.flag
     * if(aa){
     *  while(true){
     *      i++
     *  }
     * }
     */
    public boolean flag = true;

    public static void main(String[] args) throws InterruptedException { //思维逻辑上看
        VisibilityDemo demo1 = new VisibilityDemo();
        System.out.println("代码开始了");
        Thread thread1 = new Thread(new Runnable() {
            public void run() {
                int i = 0;
                while (demo1.flag) {
                    i++;
                }
                System.out.println(i);
            }
        });
        thread1.start();
        TimeUnit.SECONDS.sleep(2); //JMM 必要性
        // 设置is为false,使上面的线程结束while循环
        demo1.flag = false;
        System.out.println("被置为false了.");
    }
}

线程间操作的定义:

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

线程间操作有:

read操作(一般读,即非volatile读)
write操作(一般写,即非volatile写)
volatile read
volatile write
Lock.(锁monitor)、Unlock
线程的第一个和最后一个操作
外部操作
所有线程间操作,都存在可见性问题,JMM需要对器进行规范。

对于同步的规则定义

对于volatile变量v的写入,与所有其他线程后续对v的读同步
对于监视器m的解锁与所有后续操作对于m的加锁同步
对于每个属性写入的默认值(0,false,null)与每个线程对其进行的操作同步
启动线程的操作与线程中的第一个操作同步
在这里插入图片描述
线程T2的最后操作与线程T1发现线程T2已经结束同步。(isAlive,join可以判断线程时否终止)
在这里插入图片描述
如果线程T1中断了T2,那么线程T1的中断操作与其他所有线程发现T2被中断了同步
通过抛出InterruptedException异常,或者调用Thread.interrupted或Thread.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关系排序的冲突访问时,就称存在数据竞争
遵守了这个规则,也就意味着有些代码不能进行重排序,有些数据不能缓存

final 在jvm中的处理–没看懂 但是感觉不重要此处进记录

在这里插入图片描述

word tearing 字节处理–不重要

在这里插入图片描述

double和long的特殊处理

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值