Le mot-clé synchronized est présent dans Java depuis la prise en charge de la multithreading pour garantir un accès exclusif à des blocs de code ou des méthodes à partir de différents threads. Historiquement, c'est la réponse de Java aux problèmes classiques de race condition et de data inconsistency, qui surviennent lors d'accès simultanés à des données partagées à partir de différents threads.
Problème lors du travail avec la multithreading – garantir l'"atomicité" des opérations et empêcher des modifications contradictoires des états des objets. Une mauvaise utilisation de synchronized peut conduire à des blocages (deadlock), à une dégradation des performances ou même à une absence de synchronisation en cas de choix incorrect de l'objet-moniteur.
Solution – utiliser le mot-clé synchronized pour une méthode ou un bloc de code, où il est nécessaire de garantir qu'un seul thread exécute ce segment à la fois. Il faut choisir soigneusement l'objet de synchronisation, éviter de longues sections critiques, et pour des tâches plus complexes, utiliser des classes spéciales du paquet java.util.concurrent.
Exemple de code:
public class Counter { private int count = 0; public synchronized void increment() { count++; } public int getCount() { return count; } } // Synchronisation de seulement une partie du code sur un objet distinct: private final Object lock = new Object(); public void complexIncrement() { synchronized (lock) { // section critique count++; } }
Caractéristiques clés :
Quelle est la différence entre une méthode synchronized et un bloc synchronized ?
Une méthode synchronisée bloque le "moniteur" de l'objet (ou de la classe, si la méthode est static), un bloc synchronisé permet de spécifier explicitement l'objet-moniteur, ce qui offre plus de flexibilité.
Que se passe-t-il si plusieurs méthodes d'un même objet sont synchronisées ?
Si les deux méthodes sont marquées synchronized (pas static), les deux utilisent l'objet lui-même (this) comme moniteur. Un thread ne peut pas entrer dans l'une ou l'autre des méthodes tant qu'un autre y est présent.
Peut-on synchroniser des méthodes statiques et des méthodes non statiques ? Comment se débloquent-elles l'une par rapport à l'autre ?
Les méthodes statiques utilisent le moniteur de la classe elle-même (objet Class), les méthodes non statiques utilisent l'objet d'instance. Donc, une méthode synchronized statique et une méthode synchronized non statique ne se bloquent pas mutuellement.
Un développeur synchronise des méthodes de différents objets, mais utilise partout le même String comme moniteur. Cela entraîne un ralentissement et des blocages "aléatoires" en raison de la réutilisation de chaînes du pool.
Avantages :
Inconvénients :
Synchronisation sur un objet final privé, qui est créé uniquement à l'intérieur de la classe (private final Object lock), et les sections critiques sont minimales en durée.
Avantages :
Inconvénients :