带有 java 引用的竞争条件

发布于 2024-09-19 16:36:56 字数 113 浏览 3 评论 0原文

原子整数、长整型、布尔值等用于对相应类型进行原子更新,因为当我们对它们执行任何操作时可能会出现竞争条件,例如 ++。但是,有哪些不同的参考案例可能存在这种竞争条件呢?

最好的问候,
克沙夫

The atomic integer, long, boolean etc are used to do any atomic updates to the respective types since there may be a race condition when we execute any manipulation on them, e.g ++. But what are the different cases with references where there may be such race conditions?

Best Regards,
Keshav

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

满天都是小星星 2024-09-26 16:37:00

出于学习目的,我使用 AtomicReference 编写了一个 ConcurrentLinkQueue。

      package concurrent.AtomicE;

      import java.util.concurrent.atomic.AtomicReference;

     public class ConcurrentLinkQueue<V> {
       private final AtomicReference<Node> firstNodePointer = new AtomicReference<Node>();

   public void fastOffer(final V data){
    final Node<V> newNode = new Node<V>(data,Thread.currentThread().getName());
    System.out.println(newNode);
    AtomicReference<Node> pointer = firstNodePointer;
    for(;;){
        if(pointer.get() == null){
            if(pointer.compareAndSet(null,newNode)){
                return;
            }
        }
        pointer = pointer.get().getNext();
    }
}

private static class Node<V>{
    private AtomicReference<Node> next = new AtomicReference<Node>();
    private volatile V data = null;
    private String threadName = "";

    Node(V data1,String threadName){
        this.data = data1;
        this.threadName = threadName;
    }

    @Override
    public String toString() {
        return  "threadName=" + threadName +
                ", data=" + data;
    }

    private AtomicReference<Node> getNext() {
        return next;
    }

    private void setNext(AtomicReference<Node> next) {
        this.next = next;
    }

    private V getData() {
        return data;
    }

    private void setData(V data) {
        this.data = data;
    }
}

For learning purpose i wrote a ConcurrentLinkQueue using AtomicReference.

      package concurrent.AtomicE;

      import java.util.concurrent.atomic.AtomicReference;

     public class ConcurrentLinkQueue<V> {
       private final AtomicReference<Node> firstNodePointer = new AtomicReference<Node>();

   public void fastOffer(final V data){
    final Node<V> newNode = new Node<V>(data,Thread.currentThread().getName());
    System.out.println(newNode);
    AtomicReference<Node> pointer = firstNodePointer;
    for(;;){
        if(pointer.get() == null){
            if(pointer.compareAndSet(null,newNode)){
                return;
            }
        }
        pointer = pointer.get().getNext();
    }
}

private static class Node<V>{
    private AtomicReference<Node> next = new AtomicReference<Node>();
    private volatile V data = null;
    private String threadName = "";

    Node(V data1,String threadName){
        this.data = data1;
        this.threadName = threadName;
    }

    @Override
    public String toString() {
        return  "threadName=" + threadName +
                ", data=" + data;
    }

    private AtomicReference<Node> getNext() {
        return next;
    }

    private void setNext(AtomicReference<Node> next) {
        this.next = next;
    }

    private V getData() {
        return data;
    }

    private void setData(V data) {
        this.data = data;
    }
}
唯憾梦倾城 2024-09-26 16:36:59

AFAIK 引用不受竞争条件的影响,因为 JVM 保证引用更新是一个原子操作(与更新 long 不同,其中低 4 字节和高 4 字节在两个不同的步骤中更新)。正如 SLaks 所指出的,唯一的关键情况是compareAndSet,它本质上不是原子的。这很少与本机引用一起使用,但当需要同时更新两个(或更多)逻辑上相互依赖的变量时,它是 AtomicReference 的一个已知习惯用法。 Java 并发实践,第 15.3.1 节为此发布了一个示例,使用 AtomicReference 在一个原子操作中更新两个变量(存储在一个简单的类中)。

除了接口的一致性之外,AtomicReference 存在的主要原因是可见性安全发布。从这个意义上说,原子变量是“更好的易失性”。

AFAIK references are not subject to race condition because the JVM guarantees that the reference update is an atomic operation (unlike e.g. updating a long, where the lower and upper 4 bytes are updated in two distinct steps). The only critical case, as SLaks noted, is compareAndSet which is not atomic by nature. That is very rarely used with native references, but it is a known idiom with AtomicReference when there is a need to update two (or more) logically codependent variables at once. Java Concurrency in Practice, section 15.3.1 publishes an example for this, using an AtomicReference to update two variables (stored in a simple class) in one atomic operation.

The main reason for the existence of AtomicReference - apart from consistency of interfaces - is visibility and safe publication. In this sense, an atomic variable is a "better volatile".

人生戏 2024-09-26 16:36:59

++ 这样的操作会受到竞争条件的影响,因为它们涉及多个离散操作(获取、增量、存储)。

设置引用 (a = b) 是一个单一操作,因此不受竞争条件的影响。

对引用类型(a.someMethod())的操作可以做任何他们想做的事情,并且可能会也可能不会受到竞争条件的影响。

Operations like ++ are subject to race conditions because they involve multiple discreet operations (fetch, increment, store).

Setting a reference (a = b) is a single operation and is thus not subject to race conditions.

Operations on reference types (a.someMethod()) can do anything they want to and may or may not be subject to race conditions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文