Question

L'entier atomique, long, etc booléens sont utilisés pour faire des mises à jour atomiques aux types respectifs car il peut y avoir une condition de course quand nous exécutons toute manipulation sur eux, ++ par exemple. Mais quels sont les différents cas avec des références où il peut y avoir des conditions de course?

Cordialement,
Keshav

Était-ce utile?

La solution

références afaik ne sont pas soumis à la condition de course parce que la machine virtuelle Java garantit que la mise à jour de référence est une opération atomique (contrairement par exemple la mise à jour d'un long, où la partie inférieure et supérieure 4 octets sont mis à jour en deux étapes distinctes). Le seul cas critique, comme SLaks noté, est compareAndSet qui est pas atomique par nature. Cela est très rarement utilisé avec des références natives, mais il est un idiome connu avec AtomicReference quand il est nécessaire de mettre à jour deux (ou plus) des variables logiquement codépendance à la fois. Programmation concurrente en Java , la section 15.3.1 publie un exemple pour cela, en utilisant un AtomicReference de mettre à jour deux variables (stockées dans une classe simple) en une seule opération atomique.

La principale raison de l'existence de AtomicReference - en dehors de la cohérence des interfaces - est visibilité et publication sécurité . En ce sens, une variable atomique est une « meilleure volatile ».

Autres conseils

Les opérations telles que ++ sont soumises à des conditions de course, car ils impliquent de multiples opérations discrètes (fetch, incrément, magasin).

Définition d'une référence (a = b) est une opération simple et est donc pas soumis à des conditions de course.

Opérations sur les types de référence (a.someMethod()) peut faire tout ce qu'ils veulent et peuvent ou peuvent ne pas être soumis à des conditions de course.

Pour les besoins d'apprentissage i a écrit un ConcurrentLinkQueue en utilisant 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;
    }
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top