Académique Documents
Professionnel Documents
Culture Documents
Programmation concurrente
Qu’est-ce
Qu’est-ce qu’un
qu’un thread
thread ??
« MultiThread » :
possibilité d’exécuter
simultanément plusieurs
Programme threads dans un même
programme
« Thread » : flot de
contrôle dans un
programme séquence
d’instructions
Les
Les threads
threads en
en Java
Java
Utilité des threads
Puissance de modélisation : un monde multithread
J2SE 5.0 intègre une bibliothèque étendue d’utilitaires de plus haut niveau pour la
gestion de la concurrence : java.util.concurrent
Pools de threads, queues, collections synchronisées, verrous spéciaux…
Dans ce cours, seuls seront abordés les éléments de base de gestion de la concurrence
Thread
Permet de créer de nouveaux
threads Thread()
Thread(Runnable target)
Le « corps » du thread,
code qui sera exécuté …
void run()
void start() Interrompt l’exécution
void interrupt() du thread
Lance l’exécution du thread static void sleep(long millis)
(de sa méthode run). Suspend l’exécution
…
du thread
Le thread s’exécute jusqu’à
ce que sa méthode run se
termine
Définition
Définition de
de threads
threads
Object
<interface> Runnable
void run()
Thread
Thread()
MonThread Thread(Runnable target)
...
…
void run()
... void run()
void start()
Deuxième solution : void interrupt()
static void sleep(long millis)
Passer en paramètre …
du constructeur un
objet implémentant
l’interface Runnable MonThread Première solution :
...
Sous classer Thread
void run()
...
et redéfinir run()
Mais dans ce cas MonThread ne peut hériter d’une autre classe (héritage simple en Java)
© Sofia ZAIDENBERG CNRS Novembre 2007 6
Définir
Définir et
et lancer
lancer un
un thread
thread
en
en sous-classant
sous-classant java.lang.Thread
java.lang.Thread
Définir
Définir et
et lancer
lancer un
un thread
thread
en
en implémentant
implémentant l’interface
l’interface java.lang.Runnable
java.lang.Runnable
public Clock() {
setDaemon(true); // thread de type "démon" : il est possible de
// quitter l’interpréteur même si ce thread est
// en cours d’exécution
start(); // ce thread se lance lui-même
}
Synchronisation
Synchronisation de
de threads
threads
Attendre
Attendre la
la fin
fin d’un
d’un autre
autre thread
thread
Parfois un thread doit s’interrompre et attendre que l’exécution d’un autre thread
soit terminée
Effectué à l’aide la méthode join()
Lorsque l’on utilise des threads multiples, il faut être très prudent si on permet
à des threads différents d’accéder aux mêmes structures de données.
une liste
d’objets
thread 1 thread 2
Parcours des éléments de la liste Tri de la liste
Synchronisation
Synchronisation de
de threads
threads
sections
sections critiques
critiques
Le moyen le plus simple de garder les objets « sûrs » vis-à-vis des threads
(« thread-safe ») est de déclarer toutes leurs méthodes sensibles comme
étant synchronized.
class X { Un thread devra obtenir un verrou
... sur l’objet avant de pouvoir appeler
public synchronized void m1(...) { n’importe laquelle de ses méthodes
... synchronisées.
}
Aucun autre thread ne pourra exécuter
... une méthode synchronisée sur l’objet
} au même moment
Il est possible d’effectuer une synchronisation plus fine en spécifiant des blocs
de code synchronisés qui détiennent momentanément un verrou sur un objet
spécifié
...
public static void swap(Object[] array, int index1, index2) {
synchronized(array) {
Object tmp = array[index1]; Bloc
array[index1] = array[index2];
array[index2] = tmp;
synchronisé.
}
}
Utilise ressource1,
demande un verrou ressource1
sur celle-ci
Utilise ressource2,
demande un verrou
Utilise ressource2, sur celle-ci
demande un verrou
sur celle-ci
ressource2
Utilise ressource1,
demande un verrou
thread1 et thread2 sont sur celle-ci
tous deux interrompus et
s’attendent mutuellement
Il faut être très prudent lors d’une programmation multithread pour éviter
ce type de situation
Synchronisation
Synchronisation de
de threads
threads
Coordination
Coordination entre
entre threads
threads
oo1
1
oo2
2
oo3
3
oo4
4
… oon
n
retirer() oo2
2
oo3
3
oo4
4
… ooi
i
oo1
1
Producteur
oo1
1
oo2
2
oo3
3
oo4
4
… oon
n
Si la file est vide,
le consommateur doit
attendre que le producteur
Consommateur place de nouveaux objets
f.retirer() f.retirer()
dans la file
q.add(o);
} le producteur est
interrompu. Il doit
attendre que le
} consommateur
relâche son verrou
Interrompre le thread consommateur pour pouvoir faire un
ajout
Permettre au thread producteur d’accéder à la file
Relancer l’exécution du thread consommateur
Synchronisation
Synchronisation de
de threads
threads
Coordination
Coordination entre
entre threads
threads -- Moniteur
Moniteur
Rendez-vous entre threads est géré au sein d’un objet moniteur à l'aide de ses
méthodes wait(), notify(), notifyAll()
wait() : le thread est mis en attente infinie jusqu’à ce qu’il soit notifié
notify() : un thread notifie un seul autre thread afin de mettre fin à son
attente
notifyAll() : la notification s’adresse à tous les threads en attente
Synchronisation
Synchronisation de
de threads
threads
Coordination
Coordination entre
entre threads
threads
if (q.size() == 0) {
try {
this.wait();
}
catch (InterruptedException e) {
// ignorer cette exception
}
import java.util.LinkedList; }
AbstractCollection<E>
<<interface>> AbstractList<E>
AbstractSet<E>
Collection<E>
AbstractSequentialList<E>
LinkedHashSet<E>
<<interface>>
SortedSet<E> AbstractQueue<E> LinkedList<E> Vector<E>
PriorityQueue<E>
Synchronisation brutale :
Toutes les méthodes sont synchronisées !
lors d'accès concurrents, toute
la structure est verrouillée
Dans java 5, introduction d'un nouveau package pour offrir un meilleur
support pour la concurrence
java.util.concurrent
Collections
Collections et
et accès
accès concurrents
concurrents
java.util.concurrent propose plusieurs implémentations
des collections offrant un support pour la concurrence
java.util
AbstractCollection<E>
<<interface>> AbstractList<E>
AbstractSet<E>
Collection<E>
AbstractSequentialList<E>
LinkedHashSet<E>
<<interface>>
SortedSet<E> AbstractQueue<E> LinkedList<E> Vector<E>
PriorityQueue<E>
java.util.concurrent
Synchronisation
uniquement à Synchronisation
ArrayBlockingQueue<E> DelayQueue<E> LinkedBlockingQueue<E>
l'écriture uniquement à
l'écriture
PriorityBlockingQueue<E> SynchronousQueue<E>
CopyOnWriteArraySet<E>
Implémentation d'un Set basée sur CopyOnWriteArrayList
ConcurrentLinkedQueue<E>
Implémentation « thread-safe » de Queue sans méthodes synchronisées,
basée en interne sur une liste chaînée.
Maps
Maps et
et accès
accès concurrents
concurrents
Comme les collections, les Maps dans java.util ne sont pas thread-safe
java.util
AbstractMap<K,V>
Comme pour Vector,
synchronisation brutale :
Toutes les méthodes sont
synchronisées !
<<interface>> HashMap<K,V>
Map<K,V>
HashTable<K,V>
<<interface>>
TreeMap<K,V> SortedMap<K,V> LinkedHashMap<K,V>
IndentityHashMap<K,V>
java.util.concurrent
<<interface>>
ConcurrentMap<K,V> ConcurrentHashMap<K,V>
Conclusion
Conclusion et
et bibliographie
bibliographie
Performances
Lisibilité du code
Nouveaux packages introduits dans Java 5 pour simplifier
la programmation d'applications concurrentes
java.util.concurrent, java.util.concurrent.atomic,
java.util.concurrent.locks
Pour en savoir plus
JAVA Tutorial : “Threads: Doing Two or More Tasks at Once”, 3rd Edition,
Mary Campione, Kathy Walrath, Alison Huml , Addison Wesley
http://java.sun.com/docs/books/tutorial/essential/threads/index.html