这是复制来自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 t;
- }
- }
- }
- }
当然,这个结论是经过了验证的,自己写了一个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);
- }
-
- }