Florian Beaufumé
• Architecte logiciel Java et web
• Freelance
• www.adeliosys.fr
• www.linkedin.com/in/fbeaufume
• fr.slideshare.net/fbeaufume
• "Le nombre de transistor double tous les deux ans"
• "La fréquence double chaque 1,5 année"
Lois de Moore
• Concurrence :
• Des tâches qui peuvent se chevaucher
• Alternées ou pas
• Parallélisme :
• Exécution simultanées au niveau matériel
Concurrence vs parallélisme
• Processus découpé en threads
• Natif vs green
• Ordonnancement préemptif vs coopératif
• Time slicing
• Fonctionnalités de distribution et coordination
• Bénéfices
• Utilisation des ressources
• Réactivité
• Couts
• Complexité de conception et débugging
• Ressources par thread et context switching
Modèle multi-threads
• Thread safe < Immutable < Stateless
• Section critique
• Opération atomique
• Contention
• Deadlock
• Starvation
Définitions
• Concurrence intégrée au langage
• Basé sur des threads :
• Nom
• Priorité : 1 à 10
• Daemon ou pas
• Etat : NEW, RUNNABLE, BLOCKED, WAITING, etc.
• Pile d'appel
• Exemple :
• Mémoire partagée suivant le Java Memory Model
Java 1.0
• Permet d'implémenter un scope request :
• Sécurité (identité, droits)
• Transaction
• Tenant
• Java 1.2 : InheritableThreadLocal
Java 1.0 - ThreadLocal
• Ajout de java.util.concurrent, merci Doug Lea
• Java Memory Model
• Interactions entre les threads
et la mémoire
• "Happens before"
• Volatile :
• R et W en mémoire principale
plutôt que sur cache CPU
• Rend R et W 64 bits (long et
double) atomique
• Mais pas un incrément
• Permet de la synchronisation
simple
Java 5
• Map<K, V>
• Hashtable : synchronisée, clés et valeurs non null
• HashMap : pas synchronisée, accepte clés et valeurs nulles
• ConcurrentMap<K, V>
• Etend Map<K, V>
• Méthodes atomiques comme putIfAbsent(key, value)
• ConcurrentHashMap, implémentation efficace
Java 5 - ConcurrentHashMap
• Exécution de tâches sur pool de threads
Java 5 - Executors (1/2)
Executor
Executor
Service
ThreadPool
Executor
Interfaces Classes
Scheduled
Executor
Service
Scheduled
ThreadPool
Executor
void execute(Runnable)
Supporte Future, ex :
Future<T> submit(Callable<T> task)
Supporte scheduling, ex :
ScheduledFuture scheduleAtFixedRate(
Runnable command,
long initialDelay,
long period,
TimeUnit unit)
• Equivalent mono-JVM de MapReduce
• Décompose une tache en sous-taches et recompose le
résultat final
• Fonctionne par work-stealing
• Etendre RecursiveAction (si pas de résultat) ou
RecursiveTask (si résultat)
Java 7 - Fork/join (1/2)
• Adder
• Bonnes performances (reporte les ajouts si besoin)
• Accumulator
• Généralisation de l'Adder
Java 8 - Adders et accumulators
Java 8 - StampedLock (1/2)
synchronized
synchronized (W)
et volatile
ReentrantLock
ReentrantRWLock
StampedLock
Simplicité
Bonnes perfs en lecture
Ajout de fonctionnalités (timed
wait, try lock, etc.)
Bonnes perfs en lecture
Bonnes perfs, fonctionnalités
(upgrade de lock R en W, etc.)
Fonctionnalités
• Execution dans le ForkJoinPool commun
• Parallélisme du ForkJoinPool commun :
• Par system property :
• -Djava.util.concurrent.ForkJoinPool.common.parallelism=7
• Sinon Runtime.getRuntime().availableProcessors() - 1
• Le thread courant aussi est utilisé
• Ou dans un ForkJoinPool custom
Java 8 - Parallel streams (1/2)
• Pas toujours plus performant, varie suivant :
• Type de collection : ArrayList plutôt que LinkedList
• Nature du traitement
• Taille de "N*Q" (nb d'élément * cout par élément)
• Nombre de cœurs, il faut > 1
• Mesurer les deux
• Par défaut utilisent tous le ForkJoinPool commun
• Attention aux lambdas stateful
Java 8 - Parallel streams (2/2)
• Classe qui implémente Future et CompletionStage
• Pour combiner/chainer des actions
• Syntaxe fonctionnelle
Java 8 - CompletableFuture
• Modèle "thread-per-request" avec pools de thread
(HTTP/Servlet, EJB)
• Solutions Java SE fonctionnent mais…
• … utiliser les threads du framework
• Contextes de sécurité et de transaction
• Modèles de composants (Servlet, EJB, Spring, etc) :
• Cycle de vie et scope : request, session, etc.
• Modèle de concurrence, voir de locking
Principes généraux
• Servlet
• SingleThreadModel est déprécié
• Une instance pour toutes les requêtes, donc thread-safe
• Spring et CDI
• Concurrence manuelle via solutions de Java SE
• EJB session singleton
• @ConcurrencyManagement : container ou bean
• @AccessTimeout
• @Lock : read ou write
• Autres
Concurrence des composants
• EJB 3.1 (Java EE 6)
• Spring 3 ou Spring Data
• CDI
• Peut s'implémenter via intercepteur maison
• Evènements asynchrones de CDI 2 (Java EE 8)
Méthodes asynchrones
• Concurrence d'accès aux données entre requêtes
utilisateurs
• "Transaction longue" quand plusieurs transactions de BD
• Solutions : locking optimiste ou pessimiste
Locking de persistance
R1 W1
R2 W2
t Conflit
• Fonctionnement
• OptimisticLockException en cas de problème
• Pour faible taux de conflits
• Bénéfices
• Scalabilité
• Portabilité
• Inconvénients
• Gérer le conflit : reload, force, merge
Locking optimiste
R W
t
version=3 version=4 JPA
Hibernate "update … where version=3" "select …"
• Fonctionnement
• Pour fort taux de conflits
• Bénéfices
• Simplicité
• Inconvénients
• Contention
• Pour transactions courtes
Locking pessimiste par la base
R W
t
"select … for update" "update …"
JPA 2
Hibernate
• Fonctionnement
• Table de lock (id, entityClass, entityId, userId, date)
• Pour fort taux de conflits
• Bénéfices
• Fonctions avancées (monitoring, historisation, etc)
• Inconvénients
• Mode édition dans l'UI
• Gérer l'expiration des locks
• Plus d'accès à la base
• Contention
Locking pessimiste applicatif
R W
t
JPA
Hibernate
Lock Unlock
www.adeliosys.fr
www.linkedin.com/in/fbeaufume
fr.slideshare.net/fbeaufume
Merci