Fix race in PoolArena.allocate. Fixes #4829

Motivation:

The statistic counters PoolArena.(allocationsTiny|allocationsSmall) are
not protected by a per arena lock, but by a per size class lock. Thus,
two concurrent allocations of different size (class) could lead to a
race and ultimately to wrong statistics.

Modifications:

Use a thread-safe LongCounter instead of a plain long data type.

Result:

Fewer data races.
This commit is contained in:
buchgr 2016-03-13 22:27:56 +01:00 committed by Norman Maurer
parent ec946f8a3e
commit 47b598e6ce

View File

@ -57,8 +57,8 @@ abstract class PoolArena<T> implements PoolArenaMetric {
private final List<PoolChunkListMetric> chunkListMetrics;
// Metrics for allocations and deallocations
private long allocationsTiny;
private long allocationsSmall;
private LongCounter allocationsTiny = PlatformDependent.newLongCounter();
private LongCounter allocationsSmall = PlatformDependent.newLongCounter();
private long allocationsNormal;
// We need to use the LongCounter here as this is not guarded via synchronized block.
private final LongCounter allocationsHuge = PlatformDependent.newLongCounter();
@ -195,9 +195,9 @@ abstract class PoolArena<T> implements PoolArenaMetric {
s.chunk.initBufWithSubpage(buf, handle, reqCapacity);
if (tiny) {
++allocationsTiny;
allocationsTiny.increment();
} else {
++allocationsSmall;
allocationsSmall.increment();
}
return;
}
@ -432,17 +432,17 @@ abstract class PoolArena<T> implements PoolArenaMetric {
@Override
public long numAllocations() {
return allocationsTiny + allocationsSmall + allocationsNormal + allocationsHuge.value();
return allocationsTiny.value() + allocationsSmall.value() + allocationsNormal + allocationsHuge.value();
}
@Override
public long numTinyAllocations() {
return allocationsTiny;
return allocationsTiny.value();
}
@Override
public long numSmallAllocations() {
return allocationsSmall;
return allocationsSmall.value();
}
@Override