:: Enseignements :: ESIPE :: E4INFO :: 2019-2020 :: Collections Concurrentes ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) |
Volatile, Opérations atomiques et CompareAndSet
|
Algorithme lock-free et opérations atomiques
Exercice 1 - A vos chronometres
On cherche à savoir combien d'itérations d'une boucle on peut faire en 100 millisecondes.
Un de vos collègues a produit le code suivant:
-
Sans exécuter le code, que fait ce programme ?
-
Vérifier, en exécutant le programme (plusieurs fois), si vous avez vu juste.
-
Comment doit-on corriger le problème ?
Modifier la classe Bogus en conséquence.
-
On cherche maintenant a accélérer le code de Bogus en utilisant le mot clé volatile
au lieu des blocs synchronized.
Créer une classe BogusVolatile qui n'utilise pas de bloc synchronized.
Comment appelle-t-on les implantations qui n'ont ni blocs synchronized, ni lock ?
Exercice 2 - Compteur
On cherche à implanter un compteur thread-safe sous la forme d'une classe Counter et de sa méthode nextInt
qui renvoie les valeurs du compteur.
public class Counter {
private int counter;
public int nextInt() {
return counter++;
}
}
-
Expliquer pourquoi le code ci-dessus n'est pas thread-safe ?
Ecrire un main démontrant le problème.
-
Que se passe t'il si on déclare le champ counter volatile ?
-
A quoi correspondt la valeur de retrour de la méthode compareAndSet de la classe
AtomicInteger ?
Utiliser la méthode compareAndSet pour créer une implantation thread-safe de la classe Counter.
-
A quoi sert la méthode getAndIncrement de la classe AtomicInteger ?
Créer une nouvelle classe Counter2, marchant comme Counter, utilisant la méthode getAndIncrement
pour obtenir une implantation thread-safe.
-
Que veut dire le terme lock-free pour un algorithme ?
Les implantations Counter et Counter2 sont-elles lock-free ?
Exercice 3 - Liste chainée lock-free
On cherche à implanter une liste chainée par insertion en tête, et on utilise pour cela le code suivant
public class Linked<E> {
private static class Entry<E> {
private final E element;
private final Entry<E> next;
private Entry(E element, Entry<E> next) {
this.element = element;
this.next = next;
}
}
private Entry<E> head;
public void addFirst(E element) {
Objects.requireNonNull(element);
head = new Entry<>(element, head);
}
public int size() {
var size = 0;
for(var link = head; link != null; link = link.next) {
size ++;
}
return size;
}
}
-
Expliquer pourquoi le code ci-dessus n'est pas thread-safe ?
Ecrire un main démontrant le problème.
-
Modifier votre implantation pour rendre la classe Linked thread-safe (et lock-free) utilisant la classe
AtomicReference
et sa méthode compareAndSet.
-
Expliquer pourquoi utiliser la classe AtomicReference n'est pas super efficace ?
-
Pour les plus balèzes, créer une classe Linked2 thread-safe (et lock-free) utilisant la classe
VarHandle
au lieu de la classe AtomicReference.
Rappel: les types paramétrés sont érasés à l'exécution !
© Université de Marne-la-Vallée