java 并发编程之共享变量的实现方法
可见性 如果一个线程对共享变量值的修改,能够及时的被其他线程看到,叫做共享变量的可见性. Java 虚拟机规范试图定义一种 Java 内存模型 (JMM),来屏蔽掉各种硬件和操作系统的内存访问差异,让 Java 程序在各种平台上都能达到一致的内存访问效果. 简单来说,由于 CPU 执行指令的速度是很快的,但是内存访问的速度就慢了很多,相差的不是一个数量级,所以搞处理器的那群大佬们又在 CPU 里加了好几层高速缓存. 在 Java 内存模型里,对上述的优化又进行了一波抽象. JMM 规定所有变量都是存在主存中的,类似于上面提到的普通内存,每个线程又包含自己的工作内存,方便理解就可以看成 CPU 上的寄存器或者高速缓存. 所以线程的操作都是以工作内存为主,它们只能访问自己的工作内存,且工作前后都要把值在同步回主内存. 简单点就是,多线程中读取或修改共享变量时,首先会读取这个变量到自己的工作内存中成为一个副本,对这个副本进行改动后,再更新回主内存中. 使用工作内存和主存,虽然加快的速度,但是也带来了一些问题. 比如看下面一个例子:
假设 线程1: load i from 主存 // i = 0 i + 1 // i = 1 线程2: load i from主存 // 因为线程1还没将i的值写回主内存,所以i还是0 i + 1 //i = 1 线程1: save i to 主存 线程2: save i to 主存 如果两个线程按照上面的执行流程,那么 这种情况一般称为 失效数据,因为线程1 还没将 也可以理解成,在操作完成之后将工作内存中的副本回写到主内存,并且在其它线程从主内存将变量同步回自己的工作内存之前,共享变量的改变对其是不可见的. 有序性 有序性: 即程序执行的顺序按照代码的先后顺序执行. 举个简单的例子,看下面这段代码: int i = 0; boolean flag = false; i = 1; //语句1 flag = true; //语句2 上面代码定义了一个 从代码顺序上看,语句1 是在语句2 前面的,那么 JVM 在真正执行这段代码的时候会保证语句1 一定会在语句2 前面执行吗? 不一定,为什么呢? 这里可能会发生指令重排序. 重排序 指令重排是指 JVM 在编译 Java 代码的时候,或者 CPU 在执行 JVM 字节码的时候,对现有的指令顺序进行重新排序. 它不保证程序中各个语句的执行先后顺序同代码中的顺序一致,但是它会保证程序最终执行结果和代码顺序执行的结果是一致的(指的是不改变单线程下的程序执行结果). 虽然处理器会对指令进行重排序,但是它会保证程序最终结果会和代码顺序执行结果相同,那么它靠什么保证的呢? 再看下面一个例子: int a = 10; //语句1 int r = 2; //语句2 a = a + 3; //语句3 r = a*a; //语句4 这段代码有 4 个语句,那么可能的一个执行顺序是: 那么可不可能是这个执行顺序呢? 语句2 语句1 语句4 语句3. 不可能,因为处理器在进行重排序时是会考虑指令之间的数据依赖性,如果一个指令 Instruction 2 必须用到 Instruction 1 的结果,那么处理器会保证 Instruction 1 会在 Instruction 2 之前执行. 虽然重排序不会影响单个线程内程序执行的结果,但是多线程呢? 下面看一个例子: //线程1: context = loadContext(); //语句1 inited = true; //语句2 //线程2: while(!inited ){ sleep() } doSomethingwithconfig(context); 上面代码中,由于语句1 和语句2 没有数据依赖性,因此可能会被重排序. 假如发生了重排序,在线程1 执行过程中先执行语句2,而此时线程2 会以为初始化工作已经完成,那么就会跳出
原子性 Java 中,对基本数据类型的读取和赋值操作是原子性操作,所谓原子性操作就是指这些操作是不可中断的,要做一定做完,要么就没有执行. JMM 只实现了基本的原子性,像
volatile 关键字 volatile 关键字的两层语义 一旦一个共享变量 (类的成员变量、类的静态成员变量) 被 1) 禁止进行指令重排序. 2) 读写一个变量时,都是直接操作主内存. 在一个变量被 1.在每个 2.在每个 或许这样说有些抽象,我们看一看刚才线程A代码的例子: boolean contextReady = false; //在线程A中执行: context = loadContext(); contextReady = true; 我们给 由于加入了 也就是说,当程序执行到 volatile特性之一: volatile特性之二:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |