【发布时间】:2013-07-18 22:39:58
【问题描述】:
class Counter
{
public int i=0;
public void increment()
{
i++;
System.out.println("i is "+i);
System.out.println("i/=2 executing");
i=i+22;
System.out.println("i is (after i+22) "+i);
System.out.println("i+=1 executing");
i++;
System.out.println("i is (after i++) "+i);
}
public void decrement()
{
i--;
System.out.println("i is "+i);
System.out.println("i*=2 executing");
i=i*2;
System.out.println("i is after i*2"+i);
System.out.println("i-=1 executing");
i=i-1;
System.out.println("i is after i-1 "+i);
}
public int value()
{
return i;
} }
class ThreadA
{
public ThreadA(final Counter c)
{
new Thread(new Runnable(){
public void run()
{
System.out.println("Thread A trying to increment");
c.increment();
System.out.println("Increment completed "+c.i);
}
}).start();
}
}
class ThreadB
{
public ThreadB(final Counter c)
{
new Thread(new Runnable(){
public void run()
{
System.out.println("Thread B trying to decrement");
c.decrement();
System.out.println("Decrement completed "+c.i);
}
}).start();
}
}
class ThreadInterference
{
public static void main(String args[]) throws Exception
{
Counter c=new Counter();
new ThreadA(c);
new ThreadB(c);
}
}
在上面的代码中,ThreadA 首先获得了对 Counter 对象的访问权,并在执行一些额外操作的同时增加了该值。 ThreadA 第一次没有缓存值 i。但是在执行 i++ (在第一行)之后,它将缓存该值。后来值更新并得到 24。根据程序,由于变量 i 不是易失性的,因此更改将在 ThreadA 的本地缓存中完成,
现在当 ThreadB 访问 decrement() 方法时,i 的值由 ThreadA 更新,即 24。这怎么可能?
【问题讨论】:
-
在 Intel-32 等设备上,缓存一致性是在硬件中实现的,尽管编译器重新排序仍然会导致“问题”。值被缓存在 CPU 寄存器中的剩余问题可能只是琐碎的测试用例的问题。调用几乎任何东西,尤其是像 'println' 这样的大型东西,肯定会导致所有可能的寄存器被压入堆栈,因此至少被压入 L1 缓存。
标签: java multithreading volatile