What could be the locking / unlocking reasoning in PriorityBlockingQueue?

140 views Asked by At

I have been reading the source code of PriorityBlockingQueue in Java and I was wondering :

  1. why is the tryGrow() method releasing the lock acquired during the offer() method, just to do its thing non-blocking, and then block again when ready to replace the contents of the queue ? i mean, it could have just kept the lock it had...
  2. how come this works? growing the queue, which involves an array copy, does not cause misbehavior on concurrent adds, where the additional adds can totally come when the current add is increasing the size of the queue?
1

There are 1 answers

3
OldCurmudgeon On BEST ANSWER

Because the memory allocation can be comparatively slow and can be done while the array is unlocked.

By releasing the lock it is allowing other threads to continue functioning while it is allocating the (potentially large) new array.

As this process can be done without locks it is good practice to do so. You should only hold a lock for the minimum length of time that you have to.

Sufficient checks are made to ensure no other thread is doing this at the same time.

UNSAFE.compareAndSwapInt(this, allocationSpinLockOffset, 0, 1)

will allow only one thread into this section of code at a time.

Note the

lock.lock();
if (newArray != null && queue == array) {

This grabs the lock again and then confirms that the array it is about to replace is the same one it grabbed a copy of at the start. If it has been replaced meanwhile then it just abandons the one it has just created on the assumption that some other thread has grown the array.

If it is still the same it then copies the old data into the new bigger array and plants it back into the field.

As Kamil nicely explains.

Purpose of that unlock is only to be sure that the faster thread will grow the queue, so we will not waste time while locking the "better ones".