java - 在 int 变量上使用时,volatile 关键字的行为不符合预期
问题描述
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 中保持同步,然后也只有单线程 4th 打印 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
解决方案
为什么synchronized
在声明变量时为 getter 和 setter 使用关键字volatile
。这里不需要。你只需要可见性,而不是原子性。所以像这样改变你的代码,
public class MyTh extends Thread {
int num;
static 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());
}
int getAge() {
return age;
}
void setAge(int k) {
age = k;
}
}
首先将age
变量标记为,static
以便在类的所有实例之间共享该变量。在您之前的情况下,它是一个实例字段,因此每个实例都有自己的副本。因此,一个人所做的更改对其他人是不可见的。
最新输出如下。
Thread-0 :0:0
Thread-3 :3:0
Thread-2 :2:0
Thread-1 :1:0
Thread-4 :4:40
Thread-6 :6:40
Thread-8 :8:40
Thread-5 :5:40
Thread-7 :7:40
Thread-9 :9:40
推荐阅读
- git - 我如何分叉一个 repo 并使用“hub fork”添加为遥控器?
- symfony - 编译失败,出现 0 个错误/不一致的构建
- javascript - 使用 sequelize 链接查询
- java - 水平、垂直或对角线检测多个 4 个相同字母序列的最有效算法
- tensorflow - 在 Tensorflow Keras 分类器中使用数据集时,model.fit() 方法中的“IndexError: list index out of range”
- r - 如何旋转完整的 facet_wrap ggplot?
- c++ - 当 p 是二维数组时,为什么 p、*p、&*p 具有相同的值?
- java - JFrames 消耗什么资源?
- arrays - 在 VBA for Excel 中循环数组函数时数据类型错误
- java - JdbcTemplate 在插入时返回 UUID “预期没有结果时返回了结果。”