9
votes

Concurrence en Java: méthodes statiques synchronisées

Je veux comprendre comment le verrouillage est effectué sur des méthodes statiques en Java.

Disons que j'ai la classe suivante: xxx

C'est ma compréhension que lorsque j'appelle que quand j'appelle f.get () , le thread acquiert la verrouillage de l'objet f et lorsque je fais foo.inc () Le fil acquiert le verrouillage Sur la classe foo .

Ma question est la suivante: comment les deux appels sont-ils synchronisés les uns sur les autres? Appelle une méthode statique acquiert également une serrure sur toutes les instanciations, ou l'inverse autour (qui semble plus raisonnable)?


EDIT:

Ma question n'est pas exactement comment statique synchronisée statique fonctionne, mais comment les méthodes statiques et non statiques sont synchronisées les unes avec les autres. I.e., je ne veux pas que deux threads appellent simultanément les deux f.get () et foo.inc () , mais ces méthodes acquièrent des serrures différentes. Ma question est de savoir comment est-ce évitaable et est-il empêché dans le code ci-dessus.


0 commentaires

6 Réponses :


1
votes

statique Les verrous sont connectés à la définition et est donc partagée entre toutes les instances de ce classe . .

Synchronisation de Aucun statique s'applique uniquement à l'instance actuelle de la classe (la serrure se trouve sur la classe instance , par exemple, ceci ). Dans votre exemple, vous avez deux serrures différentes sans interrelation.

Je ne veux pas que deux threads appellent simultanément à la fois f.get () et foo.inc (), mais ces méthodes acquièrent des serrures différentes. Ma question est la suivante: comment est-ce évitaable et qu'elle est empêchée dans le code ci-dessus

Vous devez partager un verrou pour pouvoir arbitrer l'accès aux deux f.get et foo.inc () . Vous pouvez le faire soit en partageant la même serrure statique ou en verrouillage de la même instance.


0 commentaires

2
votes

Ni, l'appel synchronisé non statique n'accepte pas de verrouillage sur la classe elle-même. (Et le bloc synchronisé statique ne verrouille aucun objet instancié de cette classe.)

En d'autres termes, les appels f.get () (verrous f ) et foo.inc () (verrouille la classe FOO ) peut fonctionner simultanément. Ils ne sont pas "synchronisés".

Vous pouvez utiliser un motif différent (singleton) ou faire toutes les méthodes statiques.


3 commentaires

Pas sûr de comprendre votre commentaire - la méthode statique synchronisée acquièce une verrouillage de la classe , mais pas sur un objet créé avec celui-ci ( foo a = nouveau foo (); - foo.inc () verrouille la chose renvoyée par a.getclass () , mais pas a ). Ou je me trompe?


foo.inc () ou nouveau foo (). Inc () verrouille les uns aux autres, ce qui verra également contre foo.dec () s'il a été déclaré statique .


Oui, parce qu'ils verrouillent tous les deux la classe. Et aucun de ces acteurs d'un objet instancié de cette classe comme le A dans mon commentaire précédent ou votre nouvel objet FOO sans nom. Je ne vois pas ce qui ne va pas dans le libellé de ma réponse.



8
votes

Une méthode statique synchronisée est effectivement équivalente à: xxx

en d'autres termes, il se verrouille sur l'objet de classe associé à la classe déclarant la méthode.

de section 8.4.3.6 de Les JLS :

Une méthode synchronisée acquiert un moniteur (§17.1) avant son exécution. Pour une méthode de classe (statique), le moniteur associé à l'objet de classe pour la classe de la méthode est utilisé. Pour une méthode d'instance, le moniteur associé à cela (l'objet pour lequel la méthode a été appelé) est utilisé.


0 commentaires

0
votes

Ces deux appels ne se synchronisent pas par rapport à l'autre. C'est comme vous l'avez dit, un appelant de f.get () acquiert la serrure de f objet et appelant de foo.inc () acquiert FOO.CLASS L'objet est un. Donc, les règles de synchronisation sont les mêmes que si elles sont au lieu d'appel statique, vous appelez une méthode synchronisée d'instance avec un autre objet.


0 commentaires

9
votes

statique et instance méthodes synchronisées code> ne sont pas liées les unes aux autres, vous devez donc appliquer une synchronisation supplémentaire entre eux, comme celle-ci:

class Foo {
    private static AtomicInteger bar = new AtomicInteger(0);
    public static void inc() { bar.getAndIncrement(); }
    public int get() { return bar.get(); }
}


0 commentaires

3
votes

Si vous lisez http://download.oracle.com/javase /Tutorial/essential/concurrency/LockSync.html .

Il vous dira:

Vous pourriez vous demander ce qui se passe quand un La méthode statique synchronisée est invoquée, puisque une méthode statique est associée avec une classe, pas un objet. Dans ce cas, le fil acquiert le Verrouillage intrinsèque pour l'objet de classe associé à la classe. Ainsi accès Les champs statiques de la classe sont contrôlés par un verrou qui est distinct de la Verrouiller pour toute instance de la classe.

qui vous dit tout ce que vous avez besoin de savoir.


0 commentaires