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

/**
    * @param <E>
    */
    static class WriteDescriptor<E> {
        public E oldV;
        public E newV;
        public AtomicReferenceArray<E> addr;
        public int addr_ind;

/**
        * Creating a new descriptor.
        *
        * @param addr Operation address 对哪个数组进行写
        * @param addr_ind  Index of address 指定index
        * @param oldV old operand
        * @param newV new operand
        */
        public WriteDescriptor(AtomicReferenceArray<E> addr, int addr_ind,
                              E oldV, E newV) {
            this.addr = addr;
            this.addr_ind = addr_ind;
            this.oldV = oldV;
            this.newV = newV;
        }

/**
        * set newV.
        */
        public void doIt() {
            // 这边失败后重试的逻辑在另外的代码里.
            addr.compareAndSet(addr_ind, oldV, newV);
        }
    }

/**
    * @param <E>
    */
    static class Descriptor<E> {
        public int size;
        volatile WriteDescriptor<E> writeop;

/**
        * Create a new descriptor.
        *
        * @param size Size of the vector
        * @param writeop Executor write operation
        */
        public Descriptor(int size, WriteDescriptor<E> writeop) {
            this.size = size;
            this.writeop = writeop;
        }

/**
        *
        */
        public void completeWrite() {
            WriteDescriptor<E> tmpOp = writeop;
            if (tmpOp != null) {
                tmpOp.doIt();
                writeop = null; // this is safe since all write to writeop use
                // null as r_value.
            }
        }
    }

private AtomicReference<Descriptor<E>> descriptor;
    private static final int zeroNumFirst = Integer
            .numberOfLeadingZeros(FIRST_BUCKET_SIZE);

/**
    * Constructor.
    */
    public LockFreeVector() {
        buckets = new AtomicReferenceArray<AtomicReferenceArray<E>>(N_BUCKET);
        buckets.set(0, new AtomicReferenceArray<E>(FIRST_BUCKET_SIZE));
        descriptor = new AtomicReference<Descriptor<E>>(new Descriptor<E>(0,
                null));
    }

/**
    * add e at the end of vector.
    * 把元素e加到vector中
    *
    * @param e
    *            element added
    */
    public void push_back(E e) {
        Descriptor<E> desc;
        Descriptor<E> newd;
        do {
            desc = descriptor.get();
            desc.completeWrite();
            // desc.size  Vector 本身的大小
            // FIRST_BUCKET_SIZE  第一个一维数组的大小
            int pos = desc.size + FIRST_BUCKET_SIZE;
            // 取出pos 的前导0
            int zeroNumPos = Integer.numberOfLeadingZeros(pos);
            // zeroNumFirst  为FIRST_BUCKET_SIZE 的前导0
            // bucketInd 数据应该放到哪一个一维数组(篮子)里的
            int bucketInd = zeroNumFirst - zeroNumPos;
            // 00000000 00000000 00000000 00001000 第一个篮子满 8
            // 00000000 00000000 00000000 00011000 第二个篮子满 8 + 16
            // 00000000 00000000 00000000 00111000 第三个篮子满 8 + 16 + 32
            // ... bucketInd其实通过前导0相减, 就是为了得出来当前第几个篮子是空的.

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

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