I've got a system with many writers and a single reader, each running in a separate thread. The writers notify the reader when work is available, and the reader blocks until it is notified.
Given the number of writers, I want to use a lock-free implementation to notify the reader. Every time the reader wakes up, it resets the notification flag, does some work, and blocks waiting for more notifications to arrive.
Essentially I'm looking for the equivalent of an AtomicBoolean
with an ability to block until its value becomes true.
What I've tried so far:
- My current implementation uses a
Semaphore
. - The semaphore starts out with no permits.
- The reader blocks trying to acquire a permit.
- Writers invoke
Semaphore.release()
in order to notify the reader. - The reader invokes
Semaphore.drainPermits()
, does some work, and blocks again onSemaphore.acquire
.
What I don't like about the Semaphore
approach:
- It seems a bit heavy-handed. I only care about about the first notification arriving. I don't need to keep a count of how many other notifications came in.
- Semaphores throw an exception if their count surpasses
Integer.MAX_VALUE
. This is more of a theoretical problem than practical but still not ideal.
Is there a data structure that is equivalent to AtomicBoolean
with an ability to block waiting on a particular value?
Alternatively, is there a thread-safe manner to ensure that Semaphore
's number of permits never surpass a certain value?
CodePudding user response:
BlockingQueue<Singleton>
would do this adequately.
You would create, for example, an ArrayBlockingQueue<Singleton>(1)
, and then your waiter would look like:
queue.take();
… and the notifier would look like:
queue.offer(Singleton.INSTANCE)
… with the use of offer
ensuring that multiple releases are combined together.