为了试验多线程概念,我正在实现我自己的使用悲观锁定的AtomicInteger版本.它看起来像这样:
public class ThreadSafeInt {
public int i; // Should this be volatile?
public ThreadSafeInt(int i) {
this.i = i;
}
public synchronized int get() {
return i;
}
public synchronized int getAndIncrement() {
return this.i++;
}
// other synchronized methods for incrementAndGet(), etc...
}
Run Code Online (Sandbox Code Playgroud)
我编写了一个测试,它接受一个ThreadSafeInt实例,将它提供给数百个线程,并使每个线程调用getAndIncrement 100,000次.我所看到的是所有增量都正确发生,整数的值是精确的(number of threads) * (number of increments per thread),即使我没有在原始实例变量上使用volatile i.我期望如果我没有使用ivolatile,那么我会得到很多可见性问题,例如,线程1 i从0 递增到1,但是线程2仍然看到0的值并且还将其递增到只有1,导致最终值小于正确的值.
我知道可见性问题是随机发生的,并且可能取决于我的环境的属性,因此即使可见性问题存在固有的潜在可能性,我的测试也可以正常工作.所以我倾向于认为volatile关键字仍然是必要的.
但这是对的吗?或者我的代码有一些属性(可能是它只是一个原始变量等),我实际上可以信任它来消除对volatile关键字的需求?
我有一个JPEG图像的ByteArrayOutputStream表示(虽然我可以使用GIF或PNG,如果这样可以更好地工作).我想在表单上显示它,例如在标签或图像对象中.我受限于这样一个事实:我无法将图像写入文件,我只能将其存储在内存中.