-
Notifications
You must be signed in to change notification settings - Fork 92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Lock-free BlockingIdentifierGenerator LoHi #1610
base: main
Are you sure you want to change the base?
Conversation
9e838df
to
5a58382
Compare
private volatile LoHi loHi; | ||
|
||
public long hi(long hi) { | ||
loHi = new LoHi(hi); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Sanne
This could be made much more strict and based on the previous value while failing if it happens concurrently too (by using a compareAndSet
)
@Sanne see final long next = next();
if ( next != -1 ) {
return CompletionStages.completedFuture( next );
}
if ( getBlockSize() <= 1 ) {
return nextHiValue( connectionSupplier )
.thenApply( i -> next( i ) );
} What happen if 2 concurrent threads both see And the same can happen with a combiner as well: while within the combiner you can have more then one updates in flights, each one competing to both hit the DB and refresh the new |
5a58382
to
ad2d5b8
Compare
|
||
private static final AtomicIntegerFieldUpdater<LoHi> LO_UPDATER = AtomicIntegerFieldUpdater.newUpdater(LoHi.class, "lo"); | ||
private final long hi; | ||
private volatile long lo; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this be an int
? Especially as you're using a AtomicIntegerFieldUpdater
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's for 2 reasons: it won't change based on JOL and will make life easier due to the "blind" getAndIncrement
(which scale much buffer then a compare and set loop).
I'd challenge you in ever noticing the current |
eheh I know, but it won't cost anything to make it lock free like this I think, I'm more concerned instead by this -> #1610 (comment) |
To quote myself of the future (and @Sanne ) re #1610 (comment) this is not a "real" problem leading to break anything, but just an efficiency one; in short, if more then one concurrently try to increase the sequence due to exhaustion and succeed, but update |
@Sanne undrafting, but feel free to pick what you like for next works on this bud ;) |
This is a version that pay a single allocation cost per each
blockSize
to save any synchronized to happen.It can be made gc-free by playing some bit tricks packing both lo/hi into a
long
(and assuming there are no negative values for both, likely) - or with some more complex coordination mechanism (yet to be designed).I don't know few things yet before un-drafting:
state.next(hi)
happen do we need to enforce validation of (hi,lo) based on existing values? new hi > old hi (or diff by blockSize?) && old low >= blockSize.state.next(hi)
happen do we need to ensure some ordering of updates? eg concurrentnext(10), next(20),next(30)
updates in this pr are not yet guaranteed to be set in any specific order and I cannot see any ordering enforced in the original code, but better be safe then sorry with concurrency