关于AbstractQueuedSynchronizer的enq()方法的代码问题

这是复制来自jdk1.8源码的AbstractQueuedSynchronizer类的enq()方法

    /**
     * Inserts node into queue, initializing if necessary. See picture above.
     * @param node the node to insert
     * @return node's predecessor
     */
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            if (t == null) { // Must initialize
                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
                node.prev = t;
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }

这个// Must initialize注释引起了我的兴趣,意思是必须初始化,但是为什么是new Node()

博主思考一番之后,觉得new Node()是额外的开销,可能jdk的开发者有另外的意图,但是这里完全可以用传入的node。这样的话,每次入队的操作就减少了一次对象的创建。

    public Node enq(final Node node) {
        for (;;) {
            Node t = tail;

            if (t == null) {
                if (compareAndSetHead(node))
                    tail = head;
            } else {
                if (node != head)
                    node.prev = t;

                if (compareAndSetTail(t, node)) {
                    t.next = node;

                    return tail;
                }
            }
        }
    }

当然,这个结论是经过了验证的,自己写了一个AQS测试了一下

package juc.aqs;

import sun.misc.Unsafe;

import java.lang.reflect.Field;

/**
 * @author heyunlin
 * @version 1.0
 */
public class AbstractQueuedSynchronizer {

    private static final long headOffset;
    private static final long tailOffset;

    volatile Node head;
    volatile Node tail;
    private static final Unsafe unsafe;

    static {
        try {
            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
            theUnsafe.setAccessible(true);

            unsafe = (Unsafe) theUnsafe.get(null);
            headOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("head"));
            tailOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
        } catch (Exception ex) { throw new Error(ex); }
    }
    
    static class Node {
        private Node prev;
        
        private Node next;
        
        private Thread thread;

        public Node() { }

        public Node(Thread thread) {
            this.thread = thread;
        }

        public Node getPrev() {
            return prev;
        }

        public void setPrev(Node prev) {
            this.prev = prev;
        }

        public Node getNext() {
            return next;
        }

        public void setNext(Node next) {
            this.next = next;
        }

        public Thread getThread() {
            return thread;
        }

        public void setThread(Thread thread) {
            this.thread = thread;
        }

    }

    public Node enq(final Node node) {
        for (;;) {
            Node t = tail;

            if (t == null) {
                if (compareAndSetHead(node))
                    tail = head;
            } else {
                node.prev = t;

                if (compareAndSetTail(t, node)) {
                    t.next = node;

                    return tail;
                }
            }
        }
    }

    private boolean compareAndSetHead(Node update) {
        return unsafe.compareAndSwapObject(this, headOffset, null, update);
    }

    private boolean compareAndSetTail(Node expect, Node update) {
        return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
    }

}

测试类

package juc.aqs;

/**
 * @author heyunlin
 * @version 1.0
 */
public class AQSExample {

    public static void main(String[] args) {
        Thread thread = new Thread() {
            @Override
            public void run() {
                System.out.println("thread run...");
            }
        };
        Thread thread2 = new Thread() {
            @Override
            public void run() {
                System.out.println("thread2 run...");
            }
        };
        Thread thread3 = new Thread() {
            @Override
            public void run() {
                System.out.println("thread3 run...");
            }
        };
        AbstractQueuedSynchronizer synchronizer = new AbstractQueuedSynchronizer();

        AbstractQueuedSynchronizer.Node node = synchronizer.enq(new AbstractQueuedSynchronizer.Node(thread));
        AbstractQueuedSynchronizer.Node node2 = synchronizer.enq(new AbstractQueuedSynchronizer.Node(thread2));
        AbstractQueuedSynchronizer.Node node3 = synchronizer.enq(new AbstractQueuedSynchronizer.Node(thread3));

        System.out.println("~~~~~~~~~~~~");

        System.out.println("node = " + node);
        System.out.println("node.prev = " + node.getPrev());
        System.out.println("node.next = " + node.getNext());
        System.out.println("head = " + synchronizer.head);
        System.out.println("tail = " + synchronizer.tail);

        System.out.println("~~~~~~~~~~~~");


        System.out.println("node2 = " + node2);
        System.out.println("node2.prev = " + node2.getPrev());
        System.out.println("node2.next = " + node2.getNext());
        System.out.println("head = " + synchronizer.head);
        System.out.println("tail = " + synchronizer.tail);

        System.out.println("~~~~~~~~~~~~");

        System.out.println("node3 = " + node3);
        System.out.println("node3.prev = " + node3.getPrev());
        System.out.println("node3.next = " + node3.getNext());
        System.out.println("head = " + synchronizer.head);
        System.out.println("tail = " + synchronizer.tail);
    }

}

你可能感兴趣的:(前端,javascript,开发语言)