:: Enseignements :: ESIPE :: E4INFO :: 2025-2026 :: Collections Concurrentes ::
![[LOGO]](http://monge.univ-eiffel.fr/ens/resources/mlv.png) |
Examen de Collection Concurrente 2026 - Session 2
|
À lire absolument
Tout ce que vous devez rendre devra obligatoirement être placé dans
le répertoire EXAM à la racine de votre compte ; sinon, ce n'est pas récupéré
et vous aurez 0.
Les deux exercices de ce TP noté sont indépendants.
Exercice 1 - FixedList est-elle thread-safe ?
Le but de cet exercice est d'étudier plusieurs variations du code ci-dessous
pour déterminer s'il y a des problèmes de publication et si plus généralement,
le code est
thread-safe.
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.Objects;
public final class ThreadSafeFixedList<E> {
private static final VarHandle VH_SIZE, VH_ELEMENTS;
static {
var lookup = MethodHandles.lookup();
VH_SIZE = ... /* TODO */
VH_ELEMENTS = MethodHandles.arrayElementVarHandle(Object[].class)
.withInvokeExactBehavior();
}
private static final IllegalStateException FULL = new IllegalStateException("list is full");
private /*keyword*/ E[] elements;
private volatile int size;
public ThreadSafeFixedList(int capacity) {
if (capacity < 0) {
throw new IllegalArgumentException("capacity < 0");
}
@SuppressWarnings("unchecked")
var elements = (E[]) new Object[capacity];
this.elements = elements;
super();
}
public int size() {
return this.size; // volatile read
}
public void add(E element) {
Objects.requireNonNull(element);
var index = (int) VH_SIZE.getAndAdd(this, 1); // volatile read/write
var elements = this.elements; // plain read
if (index >= elements.length) {
throw FULL;
}
VH_ELEMENTS.setVolatile(elements, index, element); // volatile elements[index] = element;
}
@SuppressWarnings("unchecked")
public E get(int index) {
var size = this.size; // volatile read
var elements = this.elements; // plain read
if (size > elements.length) {
throw new IllegalStateException("??");
}
Objects.checkIndex(index, size);
E element;
while((element = (E) VH_ELEMENTS.getVolatile(elements, index)) == null) { // volatile read
Thread.onSpinWait();
}
return element;
}
}
-
Au niveau de la déclaration du champ elements, quel doit être le mot-clé
(à la place de /*keyword*/) ?
Justifier ! (en écrivant un commentaire dans le code)
-
À quoi sert l'appel à .withInvokeExactBehavior() pour initialiser
le champ VH_ELEMENTS ?
Écrire un commentaire au niveau de l'initialisation de VH_ELEMENTS
pour expliquer.
-
Il manque le code pour initialiser VH_SIZE (le TODO),
pouvez-vous l'écrire ?
-
Expliquer ce que fait la ligne var index = (int) VH_SIZE.getAndAdd(this, 1);
(en commentaire au dessus de la ligne).
-
Dans quel cas, la méthode get(int index) peut lever l'IllegalStateException
avec le message "??" ?
Écrivez un commentaire au-dessus de l'instruction throw pour expliquer.
-
La classe ThreadSafeFixedList est-elle thread-safe ? Si oui ou non, expliquer pourquoi.
-
On change le code de get(int index) pour
public E get(int index) {
var size = this.size; // volatile read
var elements = this.elements; // plain read
if (size > elements.length) {
throw new IllegalStateException("??");
}
Objects.checkIndex(index, size);
var element = elements[index]; // plain read
if (element != null) {
return element;
}
while((element = (E) VH_ELEMENTS.getVolatile(elements, index)) == null) { // volatile read
Thread.onSpinWait();
}
return element;
}
Avec ce nouveau code, la classe ThreadSafeFixedList est-elle thread-safe ?
Si oui ou non, expliquer pourquoi.
Exercice 2 - VectorizedIntView
On souhaite écrire une classe faisant des calculs sur un tableau d'entiers
offrant des opérations de recherche et de réduction utilisant les opérations
SIMD (vectorisées) du CPU.
public final class VectorizedIntView {
private int[] elements;
public VectorizedIntView(int... elements) {
this.elements = elements;
}
public int size() {
return elements.length;
}
public int get(int index) {
Objects.checkIndex(index, size);
return elements[index];
}
public boolean contains(int value) {
throw new UnsupportedOperationException("TODO");
}
public int indexOf(int value) {
throw new UnsupportedOperationException("TODO");
}
public record MinMax(int min, int max) {}
public MinMax minMax(int fromIndex, int toIndex) {
throw new UnsupportedOperationException("TODO");
}
public MinMax parallelMinMax() {
throw new UnsupportedOperationException("TODO");
}
}
Voici un exemple d'utilisation :
var array = new int[] {3, 1, 4, 1, 5, 9, 2, 6};
var view = new VectorizedIntView(array);
IO.println(view.contains(9)); // true
IO.println(view.indexOf(5)); // 4
IO.println(view.minMax(0, view.size())); // MinMax[min=1, max=9]
IO.println(view.parallelMinMax()); // MinMax[min=1, max=9]
Pour cet exercice, on vous demande d'utiliser le module
jdk.incubator.vector,
avec
--add-modules jdk.incubator.vector aux paramètres de la VM (en plus du
-ea).
Des tests unitaires correspondant à l'implantation sont ici :
VectorizedIntViewTest.java.
-
Écrire la méthode contains en utilisant les opérations vectorisées, avec une
post-loop pour traiter les éléments restants.
Vérifier que les tests unitaires marqués "Q1" passent.
-
Écrire la méthode indexOf, toujours vectorisée avec une post-loop.
Note : après avoir trouvé un bit à vrai dans le masque, il faut retrouver la position exacte
du bit/lane où l'égalité est vraie dans le vecteur.
Vérifier que les tests unitaires marqués "Q2" passent.
-
Écrire la méthode minMax(fromIndex, toIndex) qui calcule le minimum et le maximum
en un seul passage vectorisé sur l'intervalle [fromIndex, toIndex).
Dans le cas où il n'y a pas d'élément dans l'intervalle, une exception doit être levée.
Vérifier que les tests unitaires marqués "Q3" passent.
Note: si vous n'y arrivez pas, faite juste une version non-vectorizé et passez à la question suivante.
-
Écrire la méthode parallelMinMax qui calcule le minimum et le maximum sur toute la
vue en utilisant fork/join, en réutilisant la méthode minMax écrite précédemment
(pour les intervalles de moins de 1024 éléments), et en combinant deux résultats
partiels en prenant le minimum des minimums et le maximum des maximums.
Dans le cas où il n'y a pas d'élément, une exception doit être levée.
Vérifier que les tests unitaires marqués "Q4" passent.
© Université de Marne-la-Vallée