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