Reference counting with atomic operations¶
Reference counting with atomic operations is a memory management technique where a shared object's lifecycle is managed by a counter, manipulated using atomic hardware instructions to ensure thread safety without heavy locking.^[600-developer-big-data-netty-netty-rotate.md]
In concurrent programming, Reference counting tracks the number of active references to a resource (such as a network buffer). When the count drops to zero, the resource is deallocated.^[600-developer-big-data-netty-netty-rotate.md]
Implementation details¶
The implementation relies on a volatile integer field to store the reference count (refCnt).^[600-developer-big-data-netty-netty-rotate.md] To manage this counter efficiently, the logic typically utilizes an AtomicIntegerFieldUpdater.^[600-developer-big-data-netty-netty-rotate.md] This updater allows performant atomic operations on the standard volatile field, avoiding the memory overhead of creating AtomicInteger objects for every instance.^[600-developer-big-data-netty-netty-rotate.md]
Retaining references¶
Increasing the reference count (often called a "retain" operation) involves a loop that continuously attempts to add an increment to the current value.^[600-developer-big-data-netty-netty-rotate.md]
The core logic for incrementing is:
- Read the current count: Fetch the latest
refCntvalue.^[600-developer-big-data-netty-netty-rotate.md] - Calculate the next count: Add the desired increment to the current value.^[600-developer-big-data-netty-netty-rotate.md]
- Validate: Check if
nextCnt <= increment.^[600-developer-big-data-netty-netty-rotate.md] If this is true, it indicates that the reference count was either zero (indicating the object is dead and should not be "resurrected") or that an integer overflow has occurred.^[600-developer-big-data-netty-netty-rotate.md] - Atomic Update: Use
compareAndSet(CAS) to update the field.^[600-developer-big-data-netty-netty-rotate.md]- If the CAS succeeds (the current value in memory matches the
refCntwe read), the loop breaks.^[600-developer-big-data-netty-netty-rotate.md] - If the CAS fails (another thread modified the count), the loop repeats.^[600-developer-big-data-netty-netty-rotate.md]
- If the CAS succeeds (the current value in memory matches the
Releasing references¶
Decreasing the reference count ("release") follows a similar optimistic locking pattern.^[600-developer-big-data-netty-netty-rotate.md]
- Check bounds: Ensure the current reference count is not less than the decrement amount to prevent underflow.^[600-developer-big-data-netty-netty-rotate.md]
- Atomic Update: Use
compareAndSetto atomically swap the current count with the decremented value.^[600-developer-big-data-netty-netty-rotate.md] - Deallocate: If the CAS succeeds and the old count matches the decrement (meaning the count has hit zero), the resource is deallocated.^[600-developer-big-data-netty-netty-rotate.md]
This approach ensures that deallocation happens exactly once when the last reference is released.
Sources¶
^[600-developer-big-data-netty-netty-rotate.md]