美文网首页java多线程编程
java多线程编程-有序性

java多线程编程-有序性

作者: 李2牛 | 来源:发表于2018-04-19 12:30 被阅读0次

有序性

有序性 (Ordering) 指的是在什么情况下一个处理器上运行的一个线程所执行的内存访问操作在另一个处理器上运行的线程看来都是乱序的(Out of Order)。

导致乱序的原因有:指令的重排序和存储子系统的重排序。分别来自编译器处理器高速缓存写缓冲器

指令重排序

  1. JIT 编译器的重排序
    如果我们在多线程情况下使用这样的语句
helper = new Helper( data );

这个语句可以分解为以下三步伪操作:

1. objRef  = allocate(Helper.class);//分配所需内存空间,并获得一个指向该空间的引用
2. invokeConstuctor(objRef);//调用构造器初始化objRef 引用并指向引用的Helpe实例
3. helper = objRef;//将Helper实例引用赋值给实例变量helper

多线程环境下可能出现的情况是3指令被重排到2之前这样就导致 objRef 尚未初始化就赋值给了 helper ,使得helper出现null 的情况

  1. 处理器重排序
    处理器采用了一种叫做猜测执行(Speculation)的技术,这个技术好比是在遇到岔路的情况下,不知道走哪一条,先猜测性地走其中一条如果不通再折返选择另外一条。
package cn.likent.MultiThread;

/**
 * @author: kent
 * @date: 2018/4/19 10:16
 */
public class SpeculativeLoadExample {
    private boolean ready = false;

    private int[] data = new int[] {1,2,3,4,5,6,7,8};

    public void writer(){
        int[] newData = new int[]{1,2,3,4,5,6,7,8};

        for (int i = 0; i < newData.length; i++) {
            newData[i] = newData[i]  - i;
        }
        data  = newData;
        ready  = true;
    }
    public int reader(){
        int sum = 0 ;
        int[] snapshot;

        if(ready){
            snapshot = data;
            for (int i = 0; i < snapshot.length; i++) {
                sum += snapshot[i];//多线程的情况下,程序可能直接读取data然后计算sum,临时存放到ROB(ReOrder Buffer)中,再去读取ready的值如果ready为true 就将ROB写到主内存中,反之丢弃计算的 sum
            }
        }
        return sum;
    }
}

这个思想和CAS十分相似,总是乐观地操作,根据最终的判断决定是保存还是丢弃计算结果。但是猜测执行可能导致非预期的结果。

存储子系统重排序

类型 含义
LoadLoad 多个处理器的两个内存读操作的顺序可能不同,如两个读 操作为先L1后L1,但是其他处理器感知顺序变成了先L2后L1。下同
LoadStore 多个处理器两个内存先读后写的命令顺序可能不同
StoreLoad 多个处理器两个内存先写后读的命令顺序可能不同
StoreStore 多个处理器的两个内存写操作的顺序可能不同

貌似串行语义

类型 代码示例 说明
写后读(WAR) x = 1; y = x+1 后一条语句包含前一条语句的执行结果
读后写(RAW) y = x ; x = 1 前一条语句读取变量之后,后一条语句更新了该变量的值
写后写(WAW) x = 1;x = 2 两条语句对同一变量进行写操作

示例:

float price = 59.0f;
short quanity = 5 ;//这两句可以重排序,但是下一句依赖与这两句的执行结果,执行一定是在这两句之后
float subTotal = price * quantity;

如何保证内存访问的顺序性

可以使用 volatile 和 synchronized 关键字禁止重排序,实现有序性


回顾

相关文章

  • java多线程编程-有序性

    有序性 有序性 (Ordering) 指的是在什么情况下一个处理器上运行的一个线程所执行的内存访问操作在另一个处理...

  • 2018-10-16

    Java编程思想 1~12 java多线程编程核心技术 23~57

  • 2019-05-15 并发编程领域理论知识 - 中篇

    前言:在写java 内存模型如何解决多线程编程下的可见性和有序性的时候,以免自己或者有看的读者进入一个学习一个知识...

  • Java多线程学习:Future、Callable

    Java多线程编程:Callable、Future和FutureTask浅析(多线程编程之四) 最近在写清结算文件...

  • 史上最全Java多线程面试题及答案

    多线程并发编程是Java编程中重要的一块内容,也是面试重点覆盖区域。所以,学好多线程并发编程对Java程序员来来说...

  • Java架构师阅读书单

    一、内功心法 Java基础: 《Java核心技术》《Java编程思想》《Effective Java》 多线程...

  • Java多线程高级特性(JDK8)

    [TOC] 一、Java多线程 1.Java多线程基础知识 Java 给多线程编程提供了内置的支持。一条线程指的是...

  • 线程(Thread)

    Java 多线程编程 Java 给多线程编程提供了内置的支持。一个多线程程序包含两个或多个能并发运行的部分。程序的...

  • Java多线程编程核心技术【笔记】

    Java多线程编程核心技术【笔记】 第一章 Java多线程技能 使用多线程的场景? 阻塞 多线程提高运行效率 依赖...

  • Java socket

    Java Socket实现基于TCP和UDP多线程通信Java Socket编程

网友评论

    本文标题:java多线程编程-有序性

    本文链接:https://www.haomeiwen.com/subject/omdikftx.html