Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BlockingQueue vs Semaphore

If we want to implement a resource pool such as a database connection pool. Which concurrent collection will you use ? BlockingQueue or Semaphore ?

For BlockingQueue, just like the producer-consumer design pattern, the producer will place all the connections on the queue and the consumer will take next available connection from the queue.

For Semaphore, you specify the semaphore to the pool size, and acquire permit until you reach the pool size and wait for any of them to release the permit and putting the resource back in the pool.

Which one is simpler and easier ? and what are the scenario where we can only use one but not other ?

like image 988
peter Avatar asked Sep 04 '12 15:09

peter


People also ask

What is BlockingQueue used for?

BlockingQueue is a java Queue that support operations that wait for the queue to become non-empty when retrieving and removing an element, and wait for space to become available in the queue when adding an element.

Is BlockingQueue thread-safe?

BlockingQueue implementations are thread-safe. All queuing methods achieve their effects atomically using internal locks or other forms of concurrency control.

How does BlockingQueue work internally?

A thread trying to enqueue an element in a full queue is blocked until some other thread makes space in the queue, either by dequeuing one or more elements or clearing the queue completely. Similarly, it blocks a thread trying to delete from an empty queue until some other threads insert an item.


3 Answers

Many blocking queues are implemented with semaphores anyway, (and maybe a mutex/futex/CS). I use blocking queues for object storage a lot - once you have a blocking queue that works, why bother using anything else for an object pool?

like image 36
Martin James Avatar answered Oct 04 '22 06:10

Martin James


The BlockingQueue is simpler because it will keep track of the Connections/resource as well.

e.g.

public abstract class ResourcePool<Resource> {
    private final BlockingQueue<Resource> free;

    protected ResourcePool(int freeLimit) {
        free = new ArrayBlockingQueue<>(freeLimit);
    }

    public Resource acquire() {
        Resource resource = free.poll();
        return resource == null ? create() : resource;
    }

    public void recycle(Resource resource) {
        if (!free.offer(resource))
            close(resource);
    }

    protected abstract Resource create();

    protected abstract void close(Resource resource);
}

As you can see, the BlockingQueue helps keep track of free resources and ensure there is not too many free resources. It is thread safe without requiring explicit locking.

If you use a Semaphore, you still need to store the resources in a collection (making the semaphore redundant ;)

like image 170
Peter Lawrey Avatar answered Oct 04 '22 05:10

Peter Lawrey


For an advanced connection pool, i would probably use neither. As @PeterLawrey points out, BlockingQueue makes the most sense for a simple pool where all the resources exist initially. however, if you want to do anything more complex, like create resources on demand, then you'll most likely need additional concurrency constructs. in which case, you'll most likely end up using a simple synchronized block or Lock in the end.

like image 40
jtahlborn Avatar answered Oct 04 '22 05:10

jtahlborn