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


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

    1. /**
    2. * Inserts node into queue, initializing if necessary. See picture above.
    3. * @param node the node to insert
    4. * @return node's predecessor
    5. */
    6. private Node enq(final Node node) {
    7. for (;;) {
    8. Node t = tail;
    9. if (t == null) { // Must initialize
    10. if (compareAndSetHead(new Node()))
    11. tail = head;
    12. } else {
    13. node.prev = t;
    14. if (compareAndSetTail(t, node)) {
    15. t.next = node;
    16. return t;
    17. }
    18. }
    19. }
    20. }

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

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

    1. public Node enq(final Node node) {
    2. for (;;) {
    3. Node t = tail;
    4. if (t == null) {
    5. if (compareAndSetHead(node))
    6. tail = head;
    7. } else {
    8. if (node != head)
    9. node.prev = t;
    10. if (compareAndSetTail(t, node)) {
    11. t.next = node;
    12. return t;
    13. }
    14. }
    15. }
    16. }

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

    1. package juc.aqs;
    2. import sun.misc.Unsafe;
    3. import java.lang.reflect.Field;
    4. /**
    5. * @author heyunlin
    6. * @version 1.0
    7. */
    8. public class AbstractQueuedSynchronizer {
    9. private static final long headOffset;
    10. private static final long tailOffset;
    11. volatile Node head;
    12. volatile Node tail;
    13. private static final Unsafe unsafe;
    14. static {
    15. try {
    16. Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
    17. theUnsafe.setAccessible(true);
    18. unsafe = (Unsafe) theUnsafe.get(null);
    19. headOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("head"));
    20. tailOffset = unsafe.objectFieldOffset(AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
    21. } catch (Exception ex) { throw new Error(ex); }
    22. }
    23. static class Node {
    24. private Node prev;
    25. private Node next;
    26. private Thread thread;
    27. public Node() { }
    28. public Node(Thread thread) {
    29. this.thread = thread;
    30. }
    31. public Node getPrev() {
    32. return prev;
    33. }
    34. public void setPrev(Node prev) {
    35. this.prev = prev;
    36. }
    37. public Node getNext() {
    38. return next;
    39. }
    40. public void setNext(Node next) {
    41. this.next = next;
    42. }
    43. public Thread getThread() {
    44. return thread;
    45. }
    46. public void setThread(Thread thread) {
    47. this.thread = thread;
    48. }
    49. }
    50. public Node enq(final Node node) {
    51. for (;;) {
    52. Node t = tail;
    53. if (t == null) {
    54. if (compareAndSetHead(node))
    55. tail = head;
    56. } else {
    57. node.prev = t;
    58. if (compareAndSetTail(t, node)) {
    59. t.next = node;
    60. return tail;
    61. }
    62. }
    63. }
    64. }
    65. private boolean compareAndSetHead(Node update) {
    66. return unsafe.compareAndSwapObject(this, headOffset, null, update);
    67. }
    68. private boolean compareAndSetTail(Node expect, Node update) {
    69. return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
    70. }
    71. }

    测试类

    1. package juc.aqs;
    2. /**
    3. * @author heyunlin
    4. * @version 1.0
    5. */
    6. public class AQSExample {
    7. public static void main(String[] args) {
    8. Thread thread = new Thread() {
    9. @Override
    10. public void run() {
    11. System.out.println("thread run...");
    12. }
    13. };
    14. Thread thread2 = new Thread() {
    15. @Override
    16. public void run() {
    17. System.out.println("thread2 run...");
    18. }
    19. };
    20. Thread thread3 = new Thread() {
    21. @Override
    22. public void run() {
    23. System.out.println("thread3 run...");
    24. }
    25. };
    26. AbstractQueuedSynchronizer synchronizer = new AbstractQueuedSynchronizer();
    27. AbstractQueuedSynchronizer.Node node = synchronizer.enq(new AbstractQueuedSynchronizer.Node(thread));
    28. AbstractQueuedSynchronizer.Node node2 = synchronizer.enq(new AbstractQueuedSynchronizer.Node(thread2));
    29. AbstractQueuedSynchronizer.Node node3 = synchronizer.enq(new AbstractQueuedSynchronizer.Node(thread3));
    30. System.out.println("~~~~~~~~~~~~");
    31. System.out.println("node = " + node);
    32. System.out.println("node.prev = " + node.getPrev());
    33. System.out.println("node.next = " + node.getNext());
    34. System.out.println("head = " + synchronizer.head);
    35. System.out.println("tail = " + synchronizer.tail);
    36. System.out.println("~~~~~~~~~~~~");
    37. System.out.println("node2 = " + node2);
    38. System.out.println("node2.prev = " + node2.getPrev());
    39. System.out.println("node2.next = " + node2.getNext());
    40. System.out.println("head = " + synchronizer.head);
    41. System.out.println("tail = " + synchronizer.tail);
    42. System.out.println("~~~~~~~~~~~~");
    43. System.out.println("node3 = " + node3);
    44. System.out.println("node3.prev = " + node3.getPrev());
    45. System.out.println("node3.next = " + node3.getNext());
    46. System.out.println("head = " + synchronizer.head);
    47. System.out.println("tail = " + synchronizer.tail);
    48. }
    49. }

  • 相关阅读:
    目标检测YOLO系列从入门到精通技术详解100篇-【目标检测】3D视觉
    TypeScript
    springboot项目实现helloworld
    大数据_数据中台_数据分层
    DSP介绍及CCS
    React-View-UI组件库封装——Loading加载中
    LeetCode - 207 课程表
    基于深度卷积集成网络的视网膜多种疾病筛查和识别方法
    Go 里的超时控制
    python3使用sqlite3构建本地持久化缓存
  • 原文地址:https://blog.csdn.net/heyl163_/article/details/133759654