• volatile关键字 学习记录1


    虽然已经工作了半年了...虽然一直是在做web开发....但是平时一直很少使用多线程.....

    然后最近一直在看相关知识..所以就有了这篇文章

    用例子来说明问题吧

     1 public class VolatileTest {
     2     boolean b = false;
     3     int a = 0;
     4 
     5     public static void main(String[] args) {
     6         for (int i=0; i<1000000; i++) {
     7             VolatileTest resource = new VolatileTest();
     8             Thread t1 = new Thread(new A(resource));
     9             Thread t2 = new Thread(new B(resource));
    10             t1.start();
    11             t2.start();
    12             //System.out.println(i);
    13         }
    14     }
    15 }
    16 
    17 class A implements Runnable {
    18     VolatileTest r = null;
    19 
    20     public A(VolatileTest a) {
    21         r = a;
    22     }
    23 
    24     public void run() {
    25         r.a = 1;
    26         r.b = true;
    27     }
    28 
    29 }
    30 
    31 class B implements Runnable {
    32     VolatileTest r = null;
    33 
    34     public B(VolatileTest a) {
    35         r = a;
    36     }
    37 
    38     public void run() {
    39         while (!r.b) {
    40             Thread.yield();
    41         }
    42         int temp = r.a;
    43         if (temp == 0) {
    44             System.out.println("出现CPU指令重排");
    45         }
    46     }
    47 }

    在这个例子中我总共输出了11次出现CPU指令重排

    之所以会有这个输出,是因为虽然在A类里代码是先将r.a设置为1,再修改r.b为true.(Line:25,26)但是在CPU执行的时候仍然可能会先做第26行代码,再做25行代码..因为这2行代码之间没有什么关联.所以优化的时候可能会改变顺序.这样就导致了会输出出现CPU指令重排

    如果将VolatileTest 的b属性增加volatile关键字的话就不会有这个情况.它可以保证这个对象前面的操作与后面的操作的顺序不会相互调换.相当于把原本代码分成了2段(A类的run方法中25行之前的代码是一段,25行之后的代码是一段,只是这里run里的代码比较少),前后2段代码顺序不会调换,但是这2段代码自己内部之间的顺序还是可以调换的.

    这种问题在单线程下是不会出现的,因为如果前后2句代码之间有关联,那么CPU会保证前一句代码先于后一句代码执行.但是在多线程里得不到保证. 所以才需要volatile关键字

    我现在对volatile的理解就是它像是synchronized的弱化版本.它可以阻止一些情况下的并发问题,但是另外一些情况的并发问题是阻止不了的.(后面会写哪些情况可以哪些不可以)

  • 相关阅读:
    Xna小游戏开发【飞机空间大战】 碧血黄沙
    参考XNA官方Platformer模版,修改Platformer为横版可以滚动的小游戏 碧血黄沙
    云计算「半步巅峰」
    get_custom_field使用
    CCTM_FormElement 类
    php opendir说明
    js(chrome)打印对象函数
    operamasks.omItemSelector获取右边框ID方法
    {$vo.CreateDate|date="ymd H:i:s",###}
    添加xmlns:android="http://schemas.android.com/apk/res/android"的意思
  • 原文地址:https://www.cnblogs.com/abcwt112/p/5132800.html
Copyright © 2020-2023  润新知