无法模拟使用volatile字段修饰符



在下面的示例中

    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值对另一个线程可见。

  1. 螺纹A:b=-12;并等待
  2. 螺纹B:B=-15;打印b;出口
  3. 线程A:打印b的新值,即-15

我如何用上面的例子模拟对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

这里有一个示例

http://vanillajava.blogspot.com/2012/01/demonstrating-when-volatile-is-required.html

你可能会发现的问题有:;

  • 虽然volatile提供了一些内存一致性保证,但不使用volatile并不能保证您会看到问题
  • 在Sun/Oracle/OpenJDK JVM中,问题似乎不会发生,直到代码得到优化,即运行了10000次之后
  • 这通常涉及到一种微妙的种族状况,即使是微小的事情也可能意味着你看不到问题

根据《实践中的并发》,volatile应该只用于标志类变量。(这是布尔值)。当新状态不依赖于变量的旧状态时,应使用Volatile。。

volatile布尔标志=true;

while(flag){..//做某事;

}

当其他线程可以修改标志变量时,将通知原始线程,因为该标志被标记为volatile。否则,循环可能会永远消失。

最新更新