I'm confused about the locks in the source codes of ArrayBlockingQueue of Java.
In put(E e)
, lockInterruptibly()
is used here:
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();
insert(e);
} finally {
lock.unlock();
}
}
But in offer(E e)
, lock()
is used:
public boolean offer(E e) {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count == items.length)
return false;
else {
insert(e);
return true;
}
} finally {
lock.unlock();
}
}
As far as I know, the difference between lock()
and lockInterruptibly()
is the the later one immediately response to the interruption.
May I ask why the author choose lock()
in offer(E e)
but lockInterruptibly()
in put(E e)
? Could it be interchangeable?
I suspect the difference is because of the different semantics of offer()
and put()
. From the javadoc:
offer(E e)
Inserts the specified element at the tail of this queue if it is possible to do so immediately without exceeding the queue's capacity, returning true upon success and false if this queue is full.
put(E e)
Inserts the specified element at the tail of this queue, waiting for space to become available if the queue is full.
As put()
needs to be able to wait, it can also be interrupted. The javadoc for lockInterruptibly()
states:
If the lock is held by another thread then the current thread becomes disabled for thread scheduling purposes and lies dormant until one of two things happens:
- The lock is acquired by the current thread; or
- Some other thread interrupts the current thread.
If the current thread:
- has its interrupted status set on entry to this method; or
- is interrupted while acquiring the lock,
then
InterruptedException
is thrown and the current thread's interrupted status is cleared.
So lockInterruptibly()
allows the program to immediately respond to the thread being interrupted before or during the acquisition of the lock, where lock()
does not (to be honest, I'm not sure what would happen if the waiting thread were interrupted while waiting for lock()
, but it seems the javadoc seems to imply that the interruption would be swallowed and ignored).
Given the semantics of offer()
and put()
, I suppose those lock methods were chosen to best match the semantics of their containing methods.