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