このオブジェクト プールは、複数のスレッドで可視性の問題を引き起こす可能性がありますか? 私は特に、この種の実行シーケンスについて疑問に思っています:
- スレッド A - getObject()
- スレッド A - オブジェクトを変更します (visibleState = 42 としましょう)
- スレッド A - releaseObject()
- スレッド B - acquireObject() (A によって解放されたばかりのオブジェクトを取得します)
- スレッド A - 関係のないことをするか、死ぬ
- スレッド B - オブジェクトを変更します (visibleState = 1 としましょう)
- スレッド B - オブジェクトを表示する
- スレッド B - releaseObject()
スレッド Bが状態自体を変更した後、スレッド A からの変更がスレッド B に表示される可能性はありますか? (実際には発生しないことはわかっていますが、JLS / Javadocがこれを保証しているかどうか、またどのように保証しているかはわかりません)。
これがコードで、本質的な部分だけを表示するために削除されています。オブジェクトを作成するためのジェネリフィケーションとファクトリを省略しました。
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
public class ObjectPool {
/** Maximum number of objects to be kept in pool */
int maxPoolSize = 10;
/** First object in pool (LIFO queue) */
final AtomicReference<PoolableObject> firstObject = new AtomicReference<PoolableObject>();
/** How many objects are currently in the pool */
final AtomicInteger poolSize = new AtomicInteger();
/** Gets an object from the pool. If no object is available
* from the pool, a new object is created and returned */
public PoolableObject obtainObject() {
while (true) {
PoolableObject object = firstObject.get();
if (object == null)
break;
if (firstObject.compareAndSet(object, object.next)) {
poolSize.decrementAndGet();
return object;
}
}
// no more objects in pool, create a new object
return new PoolableObject();
}
/** Returns an object to the pool. */
public void releaseObject(final PoolableObject object) {
while (true) {
if (poolSize.get() >= maxPoolSize)
break;
final PoolableObject first = firstObject.get();
object.next = first;
if (firstObject.compareAndSet(first, object)) {
poolSize.incrementAndGet();
break;
}
}
}
}
プールによって管理されるオブジェクトは、このクラスから継承することになっています。
public class PoolableObject {
/** Links objects in pool in single linked list. */
PoolableObject next;
public int visibleState;
}