Java Language Écriture exclusive / accès en lecture simultanée


Exemple

Un processus doit parfois écrire et lire simultanément les mêmes "données".

L'interface ReadWriteLock et son implémentation ReentrantReadWriteLock permettent un modèle d'accès pouvant être décrit comme suit:

  1. Il peut y avoir un nombre quelconque de lecteurs simultanés des données. Si au moins un accès au lecteur est autorisé, aucun accès au graveur n'est possible.
  2. Il peut y avoir au plus un seul auteur pour les données. Si un accès en écriture est accordé, aucun lecteur ne peut accéder aux données.

Une implémentation pourrait ressembler à:

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class Sample {

// Our lock. The constructor allows a "fairness" setting, which guarantees the chronology of lock attributions.
protected static final ReadWriteLock RW_LOCK = new ReentrantReadWriteLock();

// This is a typical data that needs to be protected for concurrent access
protected static int data = 0;

/** This will write to the data, in an exclusive access */
public static void writeToData() {
    RW_LOCK.writeLock().lock();
    try {
        data++;
    } finally {
        RW_LOCK.writeLock().unlock();
    }
}

public static int readData() {
    RW_LOCK.readLock().lock();
    try {
        return data;
    } finally {
        RW_LOCK.readLock().unlock();
    }
}

}

NOTE 1 : Ce cas d'utilisation précis a une solution plus propre utilisant AtomicInteger , mais ce qui est décrit ici est un modèle d'accès, qui fonctionne indépendamment du fait que les données ici sont un entier atomique.

NOTE 2 : Le verrouillage de la partie lecture est vraiment nécessaire, même si cela peut ne pas paraître au lecteur occasionnel. En effet, si vous ne verrouillez pas le lecteur, un certain nombre de problèmes peuvent survenir, parmi lesquels:

  1. Les écritures de valeurs primitives ne sont pas forcément atomiques sur toutes les JVM, de sorte que le lecteur pourrait voir, par exemple, que seuls 32 bits sur 64 bits écrivent si les data étaient de type 64 bits
  2. La visibilité de l'écriture à partir d'un thread qui ne l'a pas effectuée est garantie par la JVM uniquement si nous établissons une relation Happen Before entre les écritures et les lectures. Cette relation est établie lorsque les lecteurs et les écrivains utilisent leurs verrous respectifs, mais pas autrement
Java SE 8

StampedLock des performances plus élevées sont requises, sous certains types d'utilisation, il existe un type de verrouillage plus rapide, appelé StampedLock , qui, entre autres, implémente un mode de verrouillage optimiste. Ce verrou fonctionne très différemment du ReadWriteLock , et cet exemple n'est pas transposable.