为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕哥9229398 2021-05-07 14:58:24
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:0Thread-1 :1:0Thread-2 :2:0Thread-3 :3:0Thread-4 :4:40Thread-5 :5:0Thread-6 :6:0Thread-7 :7:0Thread-8 :8:0Thread-9 :9:0
查看完整描述

3 回答

?
犯罪嫌疑人X

TA贡献2080条经验 获得超4个赞

这里有两件事:

  1. 您正在使用实例变量age并创建10个MyTh类实例,因此每个实例将拥有自己的副本,并且不会干扰彼此的操作。因此,根据@tanyehzheng的建议,您必须将其设置为静态,以便可以在所有10个实例之间共享。

  2. 您的问题是,如果我们使用static,volatile将产生什么变化

    • static仅声明该副本将在所有实例之间共享,并且在多个线程尝试更新/访问它的情况下,它不保证内存可见性。

    • 另一方面,volatile将保证内存可见性,即,如果对该变量进行了任何写操作,则所有后续读取都将看到最新值(happens-before关系)。如果仅使用静态,则不可能实现,因为CPU内核可能会缓存该值或将其存储在寄存器中。


查看完整回答
反对 回复 2021-05-19
  • 3 回答
  • 0 关注
  • 112 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信