Quelle est la raison pour laquelle «synchronisé» n’est pas autorisé dans les méthodes d’interface Java 8?

En Java 8, je peux facilement écrire:

interface Interface1 { default void method1() { synchronized (this) { // Something } } static void method2() { synchronized (Interface1.class) { // Something } } } 

Je vais obtenir la sémantique de synchronisation complète que je peux utiliser aussi dans les classes. Je ne peux cependant pas utiliser le modificateur synchronized sur les déclarations de méthode:

 interface Interface2 { default synchronized void method1() { // ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here } static synchronized void method2() { // ^^^^^^^^^^^^ Modifier 'synchronized' not allowed here } } 

Maintenant, on peut avancer que les deux interfaces se comportent de la même manière, sauf method1() établit un contrat sur method1() et method2() , ce qui est un peu plus fort que ce que fait Interface1 . Bien sûr, nous pourrions également faire valoir que les implémentations default ne devraient pas faire d’hypothèses sur l’état de la mise en œuvre concrète, ou qu’un tel mot-clé ne ferait tout simplement pas son poids.

Question:

Quelle est la raison pour laquelle le groupe d’experts JSR-335 a décidé de ne pas prendre en charge synchronized méthodes d’interface synchronized ?

C’était une décision délibérée, plutôt qu’une omission (comme cela a été suggéré ailleurs). Bien qu’au début, il puisse sembler évident que l’on souhaite prendre en charge le modificateur synchronized sur les méthodes par défaut, il s’avère que cela serait dangereux. était interdit.

Les méthodes synchronisées sont un raccourci pour une méthode qui se comporte comme si le corps entier était enfermé dans un bloc synchronized dont l’object verrou est le récepteur. Il peut sembler judicieux d’étendre cette sémantique aux méthodes par défaut; après tout, ce sont aussi des méthodes d’instance avec un récepteur. (Notez que synchronized méthodes synchronized sont entièrement une optimisation syntaxique; elles ne sont pas nécessaires, elles sont juste plus compactes que le bloc synchronized correspondant. Il y a un argument raisonnable pour dire qu’il s’agissait d’une optimisation syntaxique prématurée, et que les méthodes synchronisées causent plus de problèmes qu’elles n’en résolvent, mais ce navire a navigué depuis longtemps.)

Alors, pourquoi sont-ils dangereux? La synchronisation concerne le locking. Le locking consiste à coordonner l’access partagé à l’état mutable. Chaque object doit avoir une stratégie de synchronisation qui détermine les verrous protégeant les variables d’état. (Voir Concurrence Java en pratique , section 2.4.)

De nombreux objects utilisent comme règle de synchronisation le Java Monitor Pattern (JCiP 4.1), dans lequel l’état d’un object est protégé par son verrou insortingnsèque. Il n’y a rien de magique ou de spécial à propos de ce modèle, mais c’est pratique, et l’utilisation du mot-clé synchronized sur les méthodes suppose implicitement ce modèle.

C’est la classe qui possède l’état qui détermine la stratégie de synchronisation de cet object. Mais les interfaces ne possèdent pas l’état des objects dans lesquels elles sont mélangées. Donc, l’utilisation d’une méthode synchronisée dans une interface suppose une politique de synchronisation particulière, mais que vous n’avez pas de base raisonnable pour supposer, l’utilisation de la synchronisation n’offre aucune sécurité supplémentaire pour les threads (vous pouvez synchroniser sur le mauvais verrou). Cela vous donnerait le faux sentiment de confiance que vous avez fait quelque chose au sujet de la sécurité des threads, et aucun message d’erreur ne vous indique que la stratégie de synchronisation est incorrecte.

Il est déjà assez difficile de maintenir une stratégie de synchronisation pour un seul fichier source. il est encore plus difficile de s’assurer qu’une sous-classe respecte correctement la politique de synchronisation définie par sa super-classe. Essayer de le faire entre de telles classes faiblement couplées (une interface et les nombreuses classes qui l’implémentent) serait presque impossible et très sujet aux erreurs.

Compte tenu de tous ces arguments, quel serait l’argument? Il semble qu’ils concernent principalement le fait que les interfaces se comportent plus comme des traits. Bien que ce soit un désir compréhensible, le centre de conception des méthodes par défaut est l’évolution des interfaces, et non pas les “Traits–“. Là où les deux peuvent être atteints de manière cohérente, nous nous sums efforcés de le faire, mais lorsque l’un est en conflit avec l’autre, nous avons dû choisir l’objective de conception principal.