如何在java中最好地实现“获取和设置”?

cgvd09ve  于 2021-07-09  发布在  Java
关注(0)|答案(1)|浏览(392)

当您关注性能时,在java中实现fetch和set的最佳实践是什么?
假设我有一个排队的尾巴 tail ,某处。我自己的节点通过将尾部替换为自身来排队,将前置节点存储在一个字段中 pred .
目前,我只能这样想:

public class MyQueue{
    public static class Node{public Node pred = null;}

    public Node tail = new Node(); //sentinel node
}

然后像。。。

import sun.misc.Unsafe;

public class MyClass{
    private static long tailOffset = 0;
    public MyClass{
        //ideally, tailOffset can be hardcoded at compile time s.t. this is obsolete
       if(tailOffset <= 0){
           this.tailOffset = unsafe.objectFieldOffset(MyQueue.class.getDeclaredField("tail");
       }
    }

    MyQueue queue = new MyQueue();

    public void createAndInsertNode(){
         Node node = new Node();
         synchronized(node){
             Node pred = queue.tail;
             while(!unsafe.compareAndSwapObject(queue,tailOffset,pred,node)){
                 pred = queue.tail;
             }
             node.pred = pred;
         }
    }

    public static final Unsafe unsafe;
    static {
        try {
            Constructor<Unsafe> unsafeConstructor = Unsafe.class.getDeclaredConstructor();
            unsafeConstructor.setAccessible(true);
            unsafe = unsafeConstructor.newInstance();
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException | InstantiationException e) {
            throw new RuntimeException(e);
        }
    }
}

(还没有测试过代码,但应该能让人理解这个想法。)
我真的不喜欢用 synchronized ,在这里,因为它要求我把所有的访问 node.pred 变成一个 synchronized(node) 也要封锁。
基本上,我只想

public void createAndInsertNode(){
     Node node = new Node();
     node.pred = FetchAndSet(queue.tail,node);
}

第二行是原子的。有什么能允许这样做的吗?

yzxexxkh

yzxexxkh1#

没有必要使用 Unsafe 直接完成这样的任务。
避免同步块的一个解决方案是使用原子引用。它最终将使用您打算使用的cas指令。

@ThreadSafe
public class MyQueue {
  public static class Node {
    public Node pred = null;
  }

  public final AtomicReference<Node> tail = new AtomicReference<>(new Node());

  public void insertNewNode() {
    Node node = new Node();
    node.pred = tail.getAndSet(node);
  }
}

相关问题