多线程情况下,你的代码执行顺序可能不是顺序执行,结果会不一致
一、思考多线程情况下,程序执行顺序是否是按顺序执行首先定义x0;y0;a0;b0;然后思考a1;xb;两行代码谁先执行问题?二、实战测试2。1测试逻辑首先默认为x0;y0;a0;b0;然后开启两个线程;线程1执行:a1;xb;线程2执行:b1;ya;有且只有xb,ya两个同时先执行,才会出现xy0。所以测试是否存在xy0观察指令是否会出现重排现象。2。2代码测试publicclassOrderTest{privatestaticintx0,y0;privatestaticinta0,b0;publicstaticvoidmain(String〔〕args)throwsInterruptedException{for(longi0;iLong。MAXVALUE;i){x0;y0;a0;b0;CountDownLatch是一个同步工具类,它通过一个计数器来实现的,初始值为线程的数量。每当一个线程完成了自己的任务,计数器的值就相应得减1。当计数器到达0时,表示所有的线程都已执行完毕,然后在等待的线程就可以恢复执行任务。CountDownLatchcountDownLatchnewCountDownLatch(2);ThreadonenewThread(newRunnable(){Overridepublicvoidrun(){a1;xb;每调用一次计数器值1,直到count被减为0,代表所有线程全部执行完毕countDownLatch。countDown();}});ThreadtwonewThread(newRunnable(){Overridepublicvoidrun(){b1;ya;countDownLatch。countDown();}});one。start();two。start();等待计数器变为0,即等待所有异步线程执行完毕countDownLatch。await();if(x0y0){xy0只能是xb;ya;这两个先执行System。out。println(执行次数i发现xy0);break;}}}}2。4测试结果
在1059079(100万)发现了指令重排现象。
三、指令重排现象
概念
指令重排序是指源码顺序和程序顺序不一样,或者说程序顺序和执行的顺序不一致,重排序的对象是指令。
指令重排序是编译器处于性能考虑,在不影响程序(单线程程序)正确性的条件下进行重新排序。指令重排序不是必然发生的,指令重排序会导致线程安全问题。指令重排序也被称为处理器的乱序执行,在这种情况下尽管指令的执行顺序可能没有完全按照程序顺序执行,但是由于指令的执行结果的提交(反应到寄存器和内存中),仍然是按照程序顺序来的,因此处理器的指令重排序并不会对单线程的正确性产生影响。指令重排序不会对单线程程序的正确性产生影响,但他可能导致多线程程序出现非预期结果。四、如何解决
使用volatile的内存屏障功能。
使用volatile修饰的变量,在读或写之后会形成内存读写屏障的效果。
写屏障会确保指令重排序时,不会将写屏障之前的代码排在写屏障之后。
读屏障会确保指令重排序时,不会将读屏障之后的代码排在读屏障之前。
在1059079(100万)发现了指令重排现象。
我们用volatile修饰一下x,y,a,b变量,修改执行次数,在1059079(100万)后再加000,1059079000(10亿)再次运行观察。即
等了30分钟还没执行结束,也没出现xy0,说明volatile成功屏障了指令重排现象。