This problem is LeetCode 1188 and stated here. I am able to implement it using Java's
synchronized
keyword. Pasting the problem here before asking my question.
Implement a thread safe bounded blocking queue that has the following methods:
- BoundedBlockingQueue(int capacity) The constructor initializes the queue with a maximum capacity.
- void enqueue(int element) Adds an element to the front of the queue. If the queue is full, the calling thread is blocked until the queue is no longer full.
- int dequeue() Returns the element at the rear of the queue and removes it. If the queue is empty, the calling thread is blocked until the queue is no longer empty.
- int size() Returns the number of elements currently in the queue.
I saw a solution here. Pasting the solution has well(from the link).
class BoundedBlockingQueue {
public BoundedBlockingQueue(int capacity) {
this.enqueueSemaphore = new Semaphore(capacity);
}
public void enqueue(int element) throws InterruptedException {
enqueueSemaphore.acquire();
q.offer(element);
dequeueSemaphore.release();
}
public int dequeue() throws InterruptedException {
dequeueSemaphore.acquire();
final int element = q.poll();
enqueueSemaphore.release();
return element;
}
public int size() {
return q.size();
}
private Queue<Integer> q = new ArrayDeque<>();
private Semaphore enqueueSemaphore;
private Semaphore dequeueSemaphore = new Semaphore(0);
}
Why is this implementation correct is what is bothering me? I understand why and how the semaphores are being used. What I don't understand is that the access to the private Queue<Integer> q = new ArrayDeque<>();
is not restricted when one thread is modifying it. I mean to say if one thread is mutating the queue, another can too. How is this correct? Should not the queue be guarded by a mutex
as well apart from the use of semaphores? As per Java, the queue implementation being used is not thread safe.