浅谈Java并发编程系列(四)—— 原子性、可见性与有序性

Java内存模型是围绕着在并发过程当中如何处理原子性、可见性和有序性这3个特征来创建的,咱们来看下哪些操做实现了这3个特性。多线程

原子性(atomicity): 由Java内存模型来直接保证原子性变量操做包括read, load, assign, use, store和write。大体能够认为基本数据类型的访问读写是具备原子性的。若是应用场景须要一个更大范围的原子性保证,Java内存模型还提供了lock和unlock操做来知足需求,尽管虚拟机没有把lock和unlock操做直接开放给用户使用,可是却提供了更高层次的字节码指令monitorenter和monitorexit来隐式地使用这两个操做,这两个字节码指令反映到Java代码中就是同步块——synchronized关键字,所以在synchronized块之间的操做也具有原子性。并发

可见性(visibility): 可见性是指当一个线程修改了共享变量的值,其余线程可以当即得知这个修改。Java内存模型是经过在变量修改后将新值同步到主内存,不管是普通变量仍是volatile变量都是如此,普通变量与volatile变量的区别是,volatile的特殊规则保证了新值能当即同步到主内存,以及每次使用前当即从主内存刷新。所以,能够说volatile保证了多线程操做时变量的可见性,而普通变量不能保证这一点。this

除了volatile以外,Java还有两个关键字能实现可见性,即synchronized和final。同步块的可见性是由“对一个变量执行unlock操做以前,必须先把此变量同步回主内存中”这条规则得到的,而final关键字的可见性是指:被final修饰的字段在构造器中一旦初始化完成,而且构造器没有把"this"的引用传递出去(this引用逃逸是一件很危险的事情,其余线程有可能经过这个引用访问到“初始化了一半”的对象),那在其余线程中就能看见final字段的值。atom

有序性: Java程序自然的有序性能够总结为一句话:若是本线程内观察,全部的操做都是有序的;若是在一个线程中观察另外一个线程,全部的操做都是无序的。前半句是指“线程内表现为串行的语义”,后半句是指“指令重排序”现象和“工做内存与主内存同步延迟”现象。线程

Java语言提供了volatile和synchronized两个关键字来保证线程之间操做的有序性,volatile关键字自己就包含了禁止指令重排序的语义,而synchronized则是由“一个变量在同一时刻只容许一条线程对其进行lock操做”这条规则得到的,这条规则决定了持有同一个锁的两个同步块只能串行地进入。对象

相关文章
相关标签/搜索