187 votes

Comment fonctionnent les méthodes statiques synchronisées en Java ?

Si j'ai une classe util avec des méthodes statiques qui appellent les fonctions d'Hibernate pour réaliser un accès basique aux données. Je me demande si la synchronisation de la méthode est la bonne approche pour garantir la sécurité des fils.

Je veux que cela empêche l'accès des informations à la même instance de la base de données. Cependant, je ne suis pas sûr que le code suivant empêche l'appel de getObjectById pour toutes les classes lorsqu'il est appelé par une classe particulière.

public class Utils {
     public static synchronized Object getObjectById (Class objclass, Long id) {
           // call hibernate class
         Session session = new Configuration().configure().buildSessionFactory().openSession();
         Object obj = session.load(objclass, id);
         session.close();
         return obj;
     }

     // other static methods
}

243voto

Scott Stanchfield Points 15863

Pour aborder la question de manière plus générale...

N'oubliez pas que l'utilisation de synchronisé sur les méthodes n'est qu'un raccourci (supposez que la classe est SomeClass) :

synchronized static void foo() {
    ...
}

est la même chose que

static void foo() {
    synchronized(SomeClass.class) {
        ...
    }
}

et

synchronized void foo() {
    ...
}

est la même chose que

void foo() {
    synchronized(this) {
        ...
    }
}

Vous pouvez utiliser n'importe quel objet comme verrou. Si vous souhaitez verrouiller des sous-ensembles de méthodes statiques, vous pouvez

class SomeClass {
    private static final Object LOCK_1 = new Object() {};
    private static final Object LOCK_2 = new Object() {};
    static void foo() {
        synchronized(LOCK_1) {...}
    }
    static void fee() {
        synchronized(LOCK_1) {...}
    }
    static void fie() {
        synchronized(LOCK_2) {...}
    }
    static void fo() {
        synchronized(LOCK_2) {...}
    }
}

(pour les méthodes non statiques, il faudrait que les verrous soient des champs non statiques).

137voto

OscarRyz Points 82553

En utilisant synchronisé sur un verrou de méthode statique, vous allez synchroniser les méthodes et les attributs de la classe (par opposition aux méthodes et attributs d'instance)

Votre hypothèse est donc correcte.

Je me demande si la synchronisation de la méthode est la bonne approche pour garantir la sécurité des fils.

Pas vraiment. Vous devriez plutôt laisser cette entreprise s'occuper de votre SGBDR. Ils sont bons dans ce genre de choses.

La seule chose que vous obtiendrez en synchronisant l'accès à la base de données est de rendre votre application terriblement lente. De plus, dans le code que vous avez posté, vous construisez une Session Factory à chaque fois, de cette façon, votre application passera plus de temps à accéder à la base de données qu'à effectuer le travail réel.

Imaginez le scénario suivant :

Les clients A et B tentent d'insérer des informations différentes dans l'enregistrement X de la table T.

Avec votre approche, la seule chose que vous obtenez est de vous assurer que l'un est appelé après l'autre, alors que cela se produirait de toute façon dans la BD, parce que le SGBDR les empêchera d'insérer la moitié des informations de A et la moitié de B en même temps. Le résultat sera le même, mais seulement 5 fois (ou plus) plus lent.

Il serait sans doute préférable de jeter un coup d'œil au "Transactions et Concurrence" dans la documentation d'Hibernate. La plupart du temps, les problèmes que vous essayez de résoudre ont déjà été résolus et de manière bien plus efficace.

18voto

starblue Points 29696

Les méthodes statiques utilisent la classe comme objet de verrouillage, c'est-à-dire Utils.class dans votre exemple. Donc oui, c'est OK.

15voto

prasad Points 51

static synchronized signifie que l'on détient un verrou sur l'objet de la classe Class objet où comme synchronized signifie détenir un verrou sur l'objet de cette classe lui-même. Cela signifie que si vous accédez à une méthode synchronisée non statique dans un thread (d'exécution), vous pouvez toujours accéder à une méthode synchronisée statique en utilisant un autre thread.

Ainsi, l'accès à deux méthodes du même type (soit deux méthodes statiques, soit deux méthodes non statiques) à un moment donné par plus d'un thread n'est pas possible.

10voto

oxbow_lakes Points 70013

Pourquoi voulez-vous imposer qu'un seul thread puisse accéder à la base de données à un moment donné ?

C'est le travail du pilote de la base de données pour mettre en œuvre tout verrouillage nécessaire, en supposant qu'un Connection n'est utilisé que par un seul fil à la fois !

Il est fort probable que votre base de données soit parfaitement capable de gérer des accès multiples et parallèles.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X