Volatile关键字解读(二)
2017-07-02 17:46
225 查看
并发编程三要素
在并发编程的过程中,我们经常会遇到这三种问题:原子性、有序性和可见性原子性
即一次操作如果涉及到一个或者多个步骤,要不全部执行成功并且中途不被打断,要么全部都不执行或者全部回滚到初态怎么理解这段话呢?举个例子,最典型的就是转账交易,比如A向B转账100,A账户假设有100的余额,B账户假设余额是0。首先A减去100,这个时候应该给B加上100才能保证原子性,但这个时候如果B加100的操作被打断了,有个人这个时候想从B账户取100,此时就会报余额不足,这就是典型的非原子性,操作没有全部执行成功就被打断。
在比如数据存储,假设存储一个32位的数据需要分两步,首先存储底16位,然后在存储高16位。当存储底16位结束后,这个时候就去读取数据的值,显然不正确,因为高16位的值还未进行存储,这也是非原子性的案例。
可见性
主要指的是共享变量,当多个线程共同访问一个共享变量时,当其中有线程改变了变量的值时,其它线程就能立刻获取到最新的值上一遍讲到了内存模型的实现原因,内存中的数据会向高速缓存中拷贝一个副本,而副本中数据的改变内存是不知道的,这就是不可见性,就会导致缓存不一致的问题
有序性
是指代码指令执行的顺序是按照代码的顺序依次执行的,比如int i = 1; //(1) int j = 2; //(2) int sum = i + j; //(3)
上面的代码比较简单,两个赋值语句和一个加运算,那么上面的语句在执行的时候一定是按照(1)–(2)–(3)的顺序执行的吗?不一定,这就涉及到了另一个概念指令重排序
一般情况下,cup为了提高运行的速度和效率,会对指令按照既定的逻辑和规则进行优化,这样就会导致指令的执行可能不会按照它的顺序依次执行,但最终会保证指令执行的结果和顺序执行指令的结果是一致的。
有人会问了cup是如何做到的,这点会在下节Java内存模型中详细说明
但首次我们需要了解的一个需要遵守的原则就是有依赖关系的指令后执行:拿上面这个例子来说(3)依赖了(1)和(2),那么(3)肯定是最后一个执行,但(1)和(2)么有依赖关系,所以(1)和(2)的执行顺序就是不确定的。
在举个例子
Process processor = Context.getProcessor() //(1) boolean flag = true; //(2) while(!flag){ //(3) doSomething() } processor.start(); //(4)
我们分析一下上面的例子,首先(1)和(2)没有依赖关系,所以顺序是不定的,(3)有依赖关系所以后执行。
假设此时有两个线程A和B来执行这个程序,因为(1)和(2)顺序不定,如果A先执行的(2),此时B线程发现(3)不满足条件,直接跳出循环去执行了(4),但是(1)并没有执行,就会报空指针异常的错误
所以有序列在单线程中是没哟影响的,但是在多线程中就会有影响,因此并发多线程要保证一致性,就必须设法保证原执行、可见性和有序列
参考信息来源:
http://www.cnblogs.com/dolphin0520/p/3920373.html
相关文章推荐
- 面试点:解读关键字volatile(C语言面试题分析之一)
- volatile关键字解读
- Volatile关键字解读(一)
- 解读关键字volatile(C语言面试题分析之一)
- Volatile关键字解读(三)
- Volatile关键字解读(四)
- 解读关键字volatile
- 解读关键字volatile (C语言面试题分析之一)
- 解读关键字volatile
- 面试点:解读关键字volatile
- 多线程之volatile关键字解读
- C关键字解读——volatile, extern, struct, union, enum
- Java中的transient,volatile和strictfp关键字
- Java transient Volatile关键字
- 多线程 说说volatile关键字
- C语言中volatile关键字的作用
- Java并发编程:volatile关键字解析
- Java中的transient,volatile和strictfp关键字
- java中volatile关键字的含义
- 转载 C语言中volatile关键字的作用