跟我学编程:Java 虚拟机之指令重排序

上一篇 / 下一篇  2023-03-31 15:10:07

  什么是指令重排序?
  在实际运行时,代码指令可能并不是严格按照代码语句顺序执行的。大多数现代微处理器都会 采用将指令乱序执行(out-of-order execution,简称OoOE或OOE)的方法,在条件允许的 情况下,直接运行当前有能力立即执行的后续指令,避开获取下一条指令所需数据时造成的等 待。
  通过乱序执行的技术,处理器可以大大提高执行效率,而这就是指令重排。
  指令重排序不是必然发生的,指令重排序会导致线程安全问题。
  指令重排序也被称为处理器的乱序执行,在这种情况下尽管指令的执行顺序可能没有完全按照程序顺序执行,但是由于指令的执行结果的提交(反应到寄存器和内存中),仍然是按照程序顺序来的,因此处理器的指令重排序并不会对单线程的正确性产生影响。
  指令重排序不会对单线程程序的正确性产生影响,
  但他可能导致多线程程序出现非预期结果。
  测试逻辑
  首先默认为x = 0; y = 0; a = 0; b = 0;然后开启两个线程;
  线程1执行:a = 888;   x = b;
  线程2执行:b = 888;   y = a;
  有且只有x = b,y = a两个同时先执行,才会出现x=y=0。
  所以测试是否存在x=y=0观察指令是否会出现重排现象。
  public class OrderTest {
      private static int x = 0, y = 0;
      private static int a = 0, b = 0;
      public static void main(String[] args) throws InterruptedException{
          for(long i = 0; i < Long.MAX_VALUE; i++){
              x = 0; y = 0; a = 0; b = 0;
            
              CountDownLatch countDownLatch = new CountDownLatch(2);
            
            
            
              Thread one = new Thread(new Runnable() {
                  @Override
                  public void run() {
                      a = 888;
                      x = b;
                    
                      countDownLatch.countDown();
                  }
              });
        
        
              Thread two = new Thread(new Runnable() {
                  @Override
                  public void run() {
                
                      b = 888;
                      y = a;
                
                      countDownLatch.countDown();
                  }
              });
              one.start();
              two.start();
              //等待计数器变为0,即等待所有异步线程执行完毕
              countDownLatch.await();
              if(x == 0 && y == 0){
                  //x=y=0 只能是x = b;y = a;这两个先执行
                  System.out.println("执行次数"+i+"发现x=y=0");
                  break;
              }
          }
      }
  }
  结果:发现了指令重排现象

TAG: 软件开发 Java java

 

评分:0

我来说两句

Open Toolbar