1 java multithreading volatile
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);
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,ThreadA首先访问Counter对象并递增值并执行一些额外的操作.ThreadA第一次没有i的缓存值.但是在执行i ++之后(在第一行),它将获得缓存值.稍后更新值并获得24.根据程序,由于变量i不是易失性的,因此更改将在ThreadA的本地缓存中完成,
现在,当ThreadB访问decrement()方法时,i的值由ThreadA更新,即24.这怎么可能?
假设线程不会看到其他线程对共享数据所做的每个更新都不合适,因为假设所有线程都会立即看到彼此的更新.
重要的是要考虑不看更新的可能性 - 不要依赖它.
除了没有看到来自其他线程的更新之外还有另一个问题,请注意 - 所有操作都以"读取,修改,写入"的方式运行...如果另一个线程在您阅读之后修改了该值,您基本上就会忽略它.
例如,假设i我们到达此行时为5:
i = i * 2;
Run Code Online (Sandbox Code Playgroud)
...但在其中途,另一个线程将其修改为4.
该行可以被认为是:
int tmp = i;
tmp = tmp * 2;
i = tmp;
Run Code Online (Sandbox Code Playgroud)
如果第二个线程i在"扩展"版本的第一行之后变为4,那么即使i是volatile,4的写入仍然会被有效地丢失 - 因为到那时tmp,它是5,它将加倍到10,然后10将被写出来.
| 归档时间: |
|
| 查看次数: |
201 次 |
| 最近记录: |