Java 无法模拟使用volatile字段修改器
在下面的例子中Java 无法模拟使用volatile字段修改器,java,multithreading,Java,Multithreading,在下面的例子中 private Integer a = 10; private Integer c = -10; private int b = -10; public void acquire(){ synchronized(a){ print("acquire()"); try{ b = -12;
private Integer a = 10;
private Integer c = -10;
private int b = -10;
public void acquire(){
synchronized(a){
print("acquire()");
try{
b = -12;
//Thread.sleep(5000);
a.wait(5000);
print("acquire : "+b);
print("I have awoken");
}catch(Exception e){
e.printStackTrace();
}
}
print("Leaving acquire()");
}
public void modify(int n){
print("Entered in modfy");
synchronized(a){
try{
b = -15;
//a.wait(5000);
Thread.sleep(5000);
print("modfy : "+b);
}catch(Exception e){
e.printStackTrace();
}
}
}
线程A正在调用acquire(),线程B正在调用modify()
一个线程更改的b值对另一个线程可见
如何用上述示例模拟volatile的需求,然后在上述示例中使用volatile。如果您只是想模拟volatile的需求,只需执行以下操作:
volatile int x = 10;
public void acquire()
{
x = 15;
print("acquire()");
}
public void modify(int n)
{
print("Entered in modfy");
x = -15;
}
//Let threadA call acquire() and threadB call modify()Then print x and see (there should not be any race conditions)
如果您想让它更有趣,请添加更多的线程和方法,并尝试访问x
我这里有一个示例
你可能会发现的问题有:
- 虽然
提供了一些内存一致性保证,但不使用volatile并不保证您会看到问题volatile
- 在Sun/Oracle/OpenJDK JVM中,这个问题似乎不会发生,直到代码得到优化,即运行10000次之后
- 这通常是一个微妙的比赛条件,即使是微小的变化也可能意味着你看不到问题
当标志变量可以被其他线程修改时,会通知原始线程,因为标志被标记为volatile。否则,循环可能会永远消失。本帖前面的问题是:即使你穿过街道时没有朝两边看,也不一定会被车撞到。没有一种方法一定会失败,规则不是这样的。(就像不看就没法过马路一样,你肯定会被车撞到。)@Gray,这不是作业。我只是想在一天内澄清多线程的所有概念。@articlestack我建议,即使有十年的多线程编程经验,您仍将学习。。)@彼得拉维是真的。但至少在某种程度上,这是一个清晰的概念。让我回答其他问题,看看我学了多少。如果这么简单,也许你可以提供一个完整的例子。;)@彼得拉维:我在这里感觉到了讽刺:)。在编写带有套接字的多线程Java程序时,我使用了volatile。我会有一个公共令牌(
volatile int array
),多个线程会更新它。我想这可能是同样的道理。如果不是,请详细说明。我怀疑这并不像你建议的那么简单,但我很高兴被证明是错的。