zoukankan      html  css  js  c++  java
  • Java 多线程 -- 指令重排(HappenBefore)

    指令重排是指:代码执行顺序和预期不一致。

    代码运行一般步骤为:
    1、从内存中获取指令解码
    2、计算值
    3、执行代码操作
    4、把结果写回内存

    而写回内存的操作比较耗时,CPU为了性能,可能不会等它完成,就进行对下一个指令解码计算。

    发生指令重排是CPU为了提高性能,但必须是对结果不影响的情况,比如:
    a =1; b =2; 先计算a 或者 b 对结果来说没有影响,就有肯能发送重排;而像 a = 5; b = a*3;这样的代码则不会发生重排。

    一把发生指令重排在单线程中基本没啥影响,当时在多线程中,同时操作一个数据,如果一个读,一个写,当写的线程还没写回时,另一个线程已经开始读取了,那么这个时候就会出现和预期不一致的结果。

    写一个可能生指令重排的代码:

    public class HappenBefore {
    
    	private static int a = 0;
    	private static boolean flag = false;
    	public static void main(String[] args) throws InterruptedException {
    		for (int i = 0; i < 10; i++) {
    			a = 0;
    			flag = false;
    			// 线程1 更改数据
    			Thread t1 = new Thread(() -> {
    				a = 1;
    				flag = true;
    			});
    			// 线程2 读取数据
    			Thread t2 = new Thread(() -> {
    				if (flag) {
    					a *= 1;
    				}
    				if (a == 0) {
    					System.out.println("指令重排了-->" + a);
    				}
    			});
    			t1.start();
    			t2.start();
    			// 合并线程,让更改数据线程先运行完
    			t1.join();
    			t2.join();
    		}
    		
    	}
    }
    

    运行以上代码:
    在这里插入图片描述
    我的电脑配的是最新的4代内存,运行10次,发生两次指令重排,如果用的是老一代的内存条,发生几率应该是会大一些。

    重视基础,才能走的更远。
  • 相关阅读:
    sql.srcipt
    sowmodaldialog
    4) 删除虚拟应用程序
    JavaScript读写Cookies
    第5章 脚本运行期库对象
    npm serve md 工具 [MD]
    cleanmark 清除格式 博客内容提取 [MD]
    Hex编码 十六进制编码
    Windows Server AppFabric(Codename:"Dublin&Velocity")介绍
    WF4设计器模型:编辑范围ModelEditingScope
  • 原文地址:https://www.cnblogs.com/xzlf/p/12681522.html
Copyright © 2011-2022 走看看