我有一个共享的临时文件资源,被分成4K(或类似值)的块。文件中的每个4K都由从零开始的索引表示。对于这个共享资源,我跟踪正在使用的4K块索引,并始终返回未使用的最低索引的4K块,如果所有块都在使用,则返回-1。
这个索引的ResourceSet类有一个公共的acquire和release方法,两者都使用同步锁,其持续时间大约像生成4个随机数一样长(在CPU方面昂贵)。
因此,如下所示的代码所示,我使用了AtomicInteger“计数信号量”来防止大量线程同时进入关键部分,在acquire()上返回-1(当前不可用)如果有太多的线程。
目前,我在acquire中使用100的常量来紧密CAS循环尝试增加原子整数,并使用10的常量来允许进入关键部分的最大线程数,这足够长以创建争用。我的问题是,在具有几个线程尝试访问这些4K块的中等到高度加载的servlet引擎中,这些常量应该是什么?
这个索引的ResourceSet类有一个公共的acquire和release方法,两者都使用同步锁,其持续时间大约像生成4个随机数一样长(在CPU方面昂贵)。
因此,如下所示的代码所示,我使用了AtomicInteger“计数信号量”来防止大量线程同时进入关键部分,在acquire()上返回-1(当前不可用)如果有太多的线程。
目前,我在acquire中使用100的常量来紧密CAS循环尝试增加原子整数,并使用10的常量来允许进入关键部分的最大线程数,这足够长以创建争用。我的问题是,在具有几个线程尝试访问这些4K块的中等到高度加载的servlet引擎中,这些常量应该是什么?
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();
}
}
}