In NAKACK2, UNICAST3 and in MaxOneThreadPerSenderPolicy, we have a pattern where one or more producers add messages (to a table in NAKACK2 and UNICAST3, or to a MessageBatch in MaxOneThreadPerSenderPolicy) and then only a single thread can remove and deliver messages up the stack.
This requires synchronization around (1) determining the thread which will remove messages, (2) adding messages to the table (or batch) and (3) removing messages from the table or batch.
Unit tests DrainTest and MessageBatchDrainTest show how a simple AtomicInteger can be used to do this.