Domanda

Il numero intero atomica, lungo, booleano ecc sono utilizzati per fare eventuali aggiornamenti atomiche ai rispettivi tipi poiché ci può essere una condizione di competizione quando eseguiamo alcuna manipolazione su di loro, per esempio ++. Ma quali sono i diversi casi con riferimenti in cui ci possono essere tali condizioni di gara?

Con i migliori saluti,
Keshav

È stato utile?

Soluzione

riferimenti AFAIK non sono soggette a condizione di competizione perché la JVM garantisce che l'aggiornamento di riferimento è un'operazione atomica (a differenza ad esempio l'aggiornamento di un long, dove quello inferiore e superiore 4 byte sono aggiornate in due fasi distinte). L'unico caso critico, come notato SLaks, è compareAndSet che non è atomica per natura. Questo è usato molto raramente con i riferimenti nativi, ma è un idioma noto con AtomicReference quando v'è la necessità di aggiornare due (o più) variabili logicamente co-dipendente in una sola volta. Java Concurrency in Practice , sezione 15.3.1 pubblica un esempio di questo, utilizzando un AtomicReference per aggiornare due variabili (memorizzato in una semplice classe) in un'unica operazione atomica.

Il motivo principale per l'esistenza di AtomicReference - a parte la coerenza delle interfacce - è visibilità e la pubblicazione di sicurezza . In questo senso, una variabile atomica è una "migliore volatile".

Altri suggerimenti

Operazioni come ++ sono soggetti a condizioni di gara perché coinvolgono più operazioni discrete (fetch, incremento, negozio).

L'impostazione di un riferimento (a = b) è una singola operazione e non è quindi soggetto a condizioni di gara.

Operazioni sui tipi di riferimento (a.someMethod()) può fare tutto ciò che vogliono e può o non può essere soggetto a condizioni di gara.

Per l'apprendimento fine ho scritto una ConcurrentLinkQueue utilizzando 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;
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top