Oui tu peux mettre l'objet que tu veux, mais comme Yosh l'a déjà dit, dans la majorité des cas on se contente de this pour les méthodes d'instance et this.class pour les méthodes statiques.
En interne, les blocs synchronisés utilisent les méthodes wait et notify.
Wait endort un thread, et notify réveille un des threads endormis par un appel à wait au hasard s'il y en a un (évidemment pour les méthodes wait et notify appelées sur le même objet, pas des objets différents).
Pour la faire courte :
| public synchronized void methode () {
/* le code protégé par la section critique */
}
|
équivaut à :
| public void methode () {
synchronized(this){
/* le code protégé par la section critique */
}
}
|
et :
| public class MaClasse {
public static synchronized void methodeStatique () {
/* le code protégé par la section critique */
}
}
|
revient à :
| public class MaClasse {
public static void methodeStatique () {
Synchronized(MaClasse.class){
/* le code protégé par la section critique */
}
}
}
|
Si on décortique plus en profondeur, ceci :
| synchronized(object){
/* le code protégé par la section critique */
}
|
équivaut grosso modo à :
| while (verrou utilisé) object.wait();
/* le code protégé par la section critique */
object.notify();
|
où l'expression verrou utilisé est elle-même protégée contre les modifications concurrentes d'une façon bien précise. Si ça t'intéresse de connaître ça dans les détails, tu pourras sûrement trouver des cours au sujet de la programmation concurrente et du pattern utilisé par Java, qui s'appelle moniteur (monitor).
Mais avant de comprendre les moniteurs, il faut d'abord déjà comprendre la base, les verrous simples et les sémaphores par exemple.
Dans la programmation de tous les jours on n'a pas besoin de savoir comment ça fonctionne dans les détails, il faut juste se souvenir qu'un thread qui arrive dans une section critique en cours d'utilisation attend jusqu'à ce qu'elle soit libérée (= qu'il n'y ait plus personne dedans).
La métaphore est peut-être un peu douteuse mais imagine que le code de la section critique soit celui qui te permet de poser une pêche… si la porte des WC est verrouillée quand tu arrives devant, tu attends que celui qui est dedans en sorte. Et une fois qu'il est parti, tu entres et tu verrouilles la porte à ton tour.
Pour les cas complexes, n'hésite pas à faire un tour du côté du package java.util.concurrent.locks dans la doc.
Là-dedans il y a des éléments classiques de la programmation concurrente avec des verrous, éléments qu'on retrouve dans plusieurs autres langages de programmation et librairies.
LE verrou le plus simple s'appelle ReentrantLock, les autres sont des constructions beaucoup plus élaborées qu'on utilise dans des cas bien spécifiques, dont certaines que j'ai vues en cours, mais que je n'ai jamais utilisées dans un projet concret qui va plus loin qu'un toy project.