web-dev-qa-db-fra.com

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

Si j'ai une classe util avec des méthodes statiques qui appellera des fonctions Hibernate pour accomplir un accès de base aux données. Je me demande si l'utilisation de la méthode synchronized est la bonne approche pour garantir la sécurité des threads.

Je veux que cela empêche l'accès des informations à la même instance de base de données. Cependant, je suis maintenant sûr si le code suivant empêche getObjectById d'être appelé 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
}
172
tomato

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

Donc, votre hypothèse est correcte.

Je me demande si rendre la méthode synchronisée est la bonne approche pour garantir la sécurité des threads.

Pas vraiment. Vous devriez laisser ce travail faire votre SGBDR à la place. 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 chaque fois une Session Factory. Ainsi, 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’on appelle l’une après l’autre, quand cela se produira de toute façon dans la base de données, car le SGBDR les empêchera d’insérer la moitié des informations de A et l’autre de B en même temps. . Le résultat sera le même mais seulement 5 fois (ou plus) moins rapide.

Il serait probablement préférable de jeter un coup d'œil au chapitre "Transactions et concurrence" de la documentation d'Hibernate. La plupart du temps, les problèmes que vous essayez de résoudre ont déjà été résolus, ce qui représente une bien meilleure solution.

134
OscarRyz

Pour aborder la question plus généralement ...

N'oubliez pas que l'utilisation de méthodes synchronisées n'est qu'un raccourci (en supposant que la classe est SomeClass):

synchronized static void foo() {
    ...
}

est le même que

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

et

synchronized void foo() {
    ...
}

est le même 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, vous voudriez que les verrous soient des champs non statiques)

224
Scott Stanchfield

Les méthodes statiques utilisent la classe comme objet de verrouillage, par exemple Utils.class. Alors oui, ça va.

17
starblue

static synchronized signifie verrouiller l'objet Class de la classe alors que as synchronized signifie verrouiller l'objet de cette classe. 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 à l'aide d'un autre thread.

Ainsi, il n'est pas possible d'accéder à deux types de méthodes identiques (deux méthodes statiques ou deux méthodes non statiques) à un moment donné, avec plus d'un thread.

14
prasad

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

C’est le travail du pilote de base de données d’implémenter tout verrouillage nécessaire, en supposant que Connection n’est utilisé que par un thread à la fois!

Très probablement, votre base de données est parfaitement capable de gérer plusieurs accès parallèles

9
oxbow_lakes

S'il s'agit de quelque chose à voir avec les données de votre base de données, pourquoi ne pas utiliser le verrouillage d'isolation de la base de données à réaliser?

2
Ray Lu

Pour répondre à votre question, oui, votre réponse est la suivante: votre méthode synchronized ne peut pas être exécutée par plusieurs threads à la fois.

2
David Z