Java高并发之无锁与Atomic源码分析(7)

// 判断这个一维数组是否已经启用, 可能是第一次初始化
            if (buckets.get(bucketInd) == null) {
                //newLen  一维数组的长度, 取前一个数组长度 * 2
                int newLen = 2 * buckets.get(bucketInd - 1).length();
                // 设置失败也没关系, 只要有人初始化成功就行
                buckets.compareAndSet(bucketInd, null,
                        new AtomicReferenceArray<E>(newLen));
            }

// 在这个一位数组中,我在哪个位置
            // 0x80000000是 10000000 00000000 00000000 00000000
            // 这句话就是把上述111000, 第一个1变成了0, 得到011000, 即新值的位置.
            int idx = (0x80000000>>>zeroNumPos) ^ pos;
            // 通过bucketInd与idx来确定元素在二维数组中的位置
            // 期望写入的时候, 该位置值是null, 如果非null, 说明其他线程已经写了, 则继续循环.
            newd = new Descriptor<E>(desc.size + 1, new WriteDescriptor<E>(
                    buckets.get(bucketInd), idx, null, e));
            // 循环cas设值
        } while (!descriptor.compareAndSet(desc, newd));
        descriptor.get().completeWrite();
    }

/**
    * Remove the last element in the vector.
    *
    * @return element removed
    */
    public E pop_back() {
        Descriptor<E> desc;
        Descriptor<E> newd;
        E elem;
        do {
            desc = descriptor.get();
            desc.completeWrite();

int pos = desc.size + FIRST_BUCKET_SIZE - 1;
            int bucketInd = Integer.numberOfLeadingZeros(FIRST_BUCKET_SIZE)
                    - Integer.numberOfLeadingZeros(pos);
            int idx = Integer.highestOneBit(pos) ^ pos;
            elem = buckets.get(bucketInd).get(idx);
            newd = new Descriptor<E>(desc.size - 1, null);
        } while (!descriptor.compareAndSet(desc, newd));

return elem;
    }

/**
    * Get element with the index.
    *
    * @param index
    *            index
    * @return element with the index
    */
    @Override
    public E get(int index) {
        int pos = index + FIRST_BUCKET_SIZE;
        int zeroNumPos = Integer.numberOfLeadingZeros(pos);
        int bucketInd = zeroNumFirst - zeroNumPos;
        int idx = (0x80000000>>>zeroNumPos) ^ pos;
        return buckets.get(bucketInd).get(idx);
    }

/**
    * Set the element with index to e.
    *
    * @param index
    *            index of element to be reset
    * @param e
    *            element to set
    */
    /**
    * {@inheritDoc}
    */
    public E set(int index, E e) {
        int pos = index + FIRST_BUCKET_SIZE;
        int bucketInd = Integer.numberOfLeadingZeros(FIRST_BUCKET_SIZE)
                - Integer.numberOfLeadingZeros(pos);
        int idx = Integer.highestOneBit(pos) ^ pos;
        AtomicReferenceArray<E> bucket = buckets.get(bucketInd);
        while (true) {
            E oldV = bucket.get(idx);
            if (bucket.compareAndSet(idx, oldV, e))
                return oldV;
        }
    }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/51b69d57160bd926d840d2e47e93aab2.html