在int变量上使用时,易失性关键字的行为不符合预期

import java.util.ArrayList;


public class ThreadTest {


    public static void main(String[] args) {


        ArrayList arr = new ArrayList();        

        for (int  i =0; i<10 ; i++)

            arr.add(new MyTh(i));   

        for (int  i =0; i<10 ; i++) {

            ((Thread ) arr.get(i)).start();

        }

    }


}


class MyTh extends Thread {


   int num;


   volatile int  age;


   MyTh (int  k)


   {this.num=k; } 

   @Override

   public void run() {

    if(this.num==4){

        setAge(40);

    }

    System.out.println(Thread.currentThread().getName() + " :"+this.num + ":" + getAge());

}

    synchronized int getAge() {

       return age;

    }

    synchronized void  setAge(int  k) {

        this.age =k;

    }

}

我在这里感到困惑,为什么程序的输出只打印一次volatile变量age = 40的值。我试图使两者在getter / setter中保持同步,然后也只有第4个单线程将其打印40。为什么其他后续线程也不能读取它40?


Thread-0 :0:0

Thread-1 :1:0

Thread-2 :2:0

Thread-3 :3:0

Thread-4 :4:40

Thread-5 :5:0

Thread-6 :6:0

Thread-7 :7:0

Thread-8 :8:0

Thread-9 :9:0


慕哥9229398
浏览 113回答 3
3回答

犯罪嫌疑人X

这里有两件事:您正在使用实例变量age并创建10个MyTh类实例,因此每个实例将拥有自己的副本,并且不会干扰彼此的操作。因此,根据@tanyehzheng的建议,您必须将其设置为静态,以便可以在所有10个实例之间共享。您的问题是,如果我们使用static,volatile将产生什么变化:static仅声明该副本将在所有实例之间共享,并且在多个线程尝试更新/访问它的情况下,它不保证内存可见性。另一方面,volatile将保证内存可见性,即,如果对该变量进行了任何写操作,则所有后续读取都将看到最新值(happens-before关系)。如果仅使用静态,则不可能实现,因为CPU内核可能会缓存该值或将其存储在寄存器中。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java