Lock-free TransactionIdCounter implementation and overflow fix#51
Lock-free TransactionIdCounter implementation and overflow fix#51khresth wants to merge 1 commit intoesa:masterfrom
Conversation
|
Hi, I am not quite sure what issue you solved. Note that the previous implementation was focused on two main things:
Can you explain to me your logic? Best regards, |
The issue I fixed is an overflow bug that causes non-monotonic transaction IDs. When the 16-bit counter exceeds MAX_OFFSET (65535), the old code recalculates partAB and resets the counter to 0, then returns partAB + 0. The problem is the counter was already incremented to 65536 before the check, so the returned ID actually jumps backward (from oldPartAB + 65535 to newPartAB + 0), breaking the strictly-increasing property. My fix returns recalculatePartAB() + 1 instead, ensuring IDs continue increasing monotonically even across overflow boundaries. Regarding the synchronized suggestion: the synchronized keyword on a static method uses the class monitor, but TransactionIdCounter is called from InteractionConsumerMap which synchronizes on a different object (transactions). These are different locks, so a plain long would race under concurrent access from different threads. The CAS approach is actually faster (about 10-20ns vs 100+ns for synchronized) and eliminates contention entirely. The idsAreStrictlyIncreasingSingleThreaded unit test catches this bug by verifying that 1000 consecutive IDs are strictly increasing, which fails on the old implementation when the counter overflows. |
Replaced synchronized lock with lock-free CAS implementation in
TransactionIdCounterto reduce contention. Fixed overflow bug.Changes
AtomicLongrecalculatePartAB() + 1instead ofpartAB + 0Testing
All new unit tests pass, including concurrent access test (16 threads × 500 IDs).