4K(またはそのような値)のチャンクに分割された共有tempfileリソースがあります。ファイル内の各4Kは、ゼロから始まるインデックスで表されます。この共有リソースでは、使用中の4Kチャンクインデックスを追跡し、使用されていない最も低いインデックスの4Kチャンクを常に返します。すべてが使用されている場合は、-1を返します。
インデックス用のこのResourceSetクラスには、パブリックの取得および解放メソッドがあり、どちらも同期ロックを使用します。このロックの期間は、4つの乱数を生成する場合とほぼ同じです(高価、CPU単位)。
したがって、次のコードからわかるように、AtomicIntegerの「カウントセマフォ」を使用して、acquire()で多数のスレッドが同時にクリティカルセクションに入るのを防ぎ、次の場合に-1(現在は使用できません)を返します。スレッドが多すぎます。
現在、タイトなCASループに定数100を使用して、取得時にアトミック整数をインクリメントしようとしています。また、クリティカルセクションに入ることができるスレッドの最大数に定数10を使用しています。これは、競合を引き起こすのに十分な長さです。 。私の質問は、これらの4Kチャンクにアクセスしようとする複数のスレッドを持つ中程度から高負荷のサーブレットエンジンの場合、これらの定数はどうあるべきかということです。
public class ResourceSet {
// ??? what should this be
// maximum number of attempts to try to increment with CAS on acquire
private static final int CAS_MAX_ATTEMPTS = 50;
// ??? what should this be
// maximum number of threads contending for lock before returning -1 on acquire
private static final int CONTENTION_MAX = 10;
private AtomicInteger latch = new AtomicInteger(0);
... member variables to track free resources
private boolean aquireLatchForAquire ()
{
for (int i = 0; i < CAS_MAX_ATTEMPTS; i++) {
int val = latch.get();
if (val == -1)
throw new AssertionError("bug in ResourceSet"); // this means more threads than can exist on any system, so its a bug!
if (!latch.compareAndSet(val, val+1))
continue;
if (val < 0 || val >= CONTENTION_MAX) {
latch.decrementAndGet();
// added to fix BUG that comment pointed out, thanks!
return false;
}
}
return false;
}
private void aquireLatchForRelease ()
{
do {
int val = latch.get();
if (val == -1)
throw new AssertionError("bug in ResourceSet"); // this means more threads than can exist on any system, so its a bug!
if (latch.compareAndSet(val, val+1))
return;
} while (true);
}
public ResourceSet (int totalResources)
{
... initialize
}
public int acquire (ResourceTracker owned)
{
if (!aquireLatchForAquire())
return -1;
try {
synchronized (this) {
... algorithm to compute minimum free resoource or return -1 if all in use
return resourceindex;
}
} finally {
latch.decrementAndGet();
}
}
public boolean release (ResourceIter iter)
{
aquireLatchForRelease();
try {
synchronized (this) {
... iterate and release all resources
}
} finally {
latch.decrementAndGet();
}
}
}