PriorityBlockingQueue 实现原理

PriorityBlockingQueue是线程安全的,之前我们看过priorityqueue的实现原理,https://www.jianshu.com/p/b0a2615f1bba?v=1672747035605

今天我们看一下PriorityBlockingQueue怎么实现线程安全的

有个类的全局变量retrantlock。是在PriorityBlockingQueue的构造方法里面新建的。


offer方法里面使用了retrantlock锁处理保证线程安全

在offer元素过程中可能需要扩容

扩容代码实现



private void tryGrow(Object[] array, int oldCap) {

lock.unlock(); // must release and then re-acquire main lock。//注释一 释放全局锁

    Object[] newArray =null;

if (allocationSpinLock ==0 &&UNSAFE.compareAndSwapInt(this, allocationSpinLockOffset, 0, 1)) {//注释二

try {

int newCap = oldCap + ((oldCap <64) ?

(oldCap +2) :// grow faster if small

                                  (oldCap >>1));

            if (newCap -MAX_ARRAY_SIZE >0) {// possible overflow

                int minCap = oldCap +1;

                if (minCap <0 || minCap >MAX_ARRAY_SIZE)

throw new OutOfMemoryError();

                newCap =MAX_ARRAY_SIZE;

            }

if (newCap > oldCap &&queue == array)

newArray =new Object[newCap];

        }finally {

allocationSpinLock =0;

        }

}if (newArray ==null)// back off if another thread is allocating

        Thread.yield();

    lock.lock(); //注释三

    if (newArray !=null &&queue == array) {

     queue = newArray;

        System.arraycopy(array, 0, newArray, 0, oldCap);  

  }}



入队时如何保证线程安全和效率

1.offer方法里面获取了自旋锁,保证了只有一个线程进行添加操作。

2.扩容方法(注释一 )会释放锁。这样保证offer方法可以进行入队操作

3.注释二  cas操作保证只有一个线程进行扩容

4.然后获取锁进行数据拷贝到扩容后的数组,因为这个操作会随着数据的增长耗费些时间。

所以采用了加锁操作。其他线程会进行yield然后进行自旋。

出队时用的就是加锁来实现的

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容