このオブジェクトプールは、複数のスレッドで可視性の問題を引き起こす可能性がありますか?私は、具体的実行シーケンスのこのような疑問を抱いています:この同期化されていないオブジェクトプールの実装は良好/安全ですか?
- スレッドA - obtainObject()
- スレッドAは - releaseObject() - オブジェクト(visibleState = 42を言うことができます)
- スレッドAを修正します
- スレッドB - obtainObject()(単にAでリリースされたオブジェクトを取得します)
- スレッドA - 関係のない何かをするか、
- スレッドBを死ぬ - (visibleState = 1を言うことができます)オブジェクトを変更
- スレッドB - プリントvisibleState
- スレッドBオブジェクト - releaseObjectを()
スレッドAから修飾はおそらく状態自体を変更したB後に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;
}
実際にここにキューはありませんか? –
firstObjectのコメントを参照してくださいか?たぶん私の英語は私にはうまくいかないかもしれませんが、1つのリンクされたリストを合理的に「キュー」と呼ぶことができます。 – Durandal
おそらく、キューのようには使用されていません。サイズ1の['ArrayBlockingQueue'](http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ArrayBlockingQueue.html)は、正しく使用する方がはるかに簡単ですし、 'SynchronousQueue'](http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/SynchronousQueue.html)を参照してください。 –