Domanda

I Tutorial Java dicono: "non è possibile interlacciare due invocazioni di metodi sincronizzati sullo stesso oggetto."

Cosa significa questo per un metodo statico? Poiché un metodo statico non ha oggetti associati, la parola chiave sincronizzata si bloccherà sulla classe anziché sull'oggetto?

È stato utile?

Soluzione

  

Poiché un metodo statico non ha oggetti associati, la parola chiave sincronizzata si bloccherà sulla classe, invece che sull'oggetto?

Sì. :)

Altri suggerimenti

Solo per aggiungere un piccolo dettaglio alla risposta di Oscar (piacevolmente concisa!), la sezione pertinente sulla specifica del linguaggio Java è 8.4.3.6," Metodi sincronizzati ":

  

Un metodo sincronizzato acquisisce un monitor (& # 167; 17.1) prima che venga eseguito. Per un metodo di classe (statico), viene utilizzato il monitor associato all'oggetto Class per la classe del metodo. Per un metodo di istanza, viene utilizzato il monitor associato a questo (l'oggetto per cui è stato invocato il metodo).

Un punto su cui devi stare attento (molti programmatori generalmente cadono in quella trappola) è che non esiste alcun collegamento tra metodi statici sincronizzati e metodi non statici sincronizzati, ovvero:

class A {
    static synchronized f() {...}
    synchronized g() {...}
}

principale:

A a = new A();

Discussione 1:

A.f();

Discussione 2:

a.g();

f () eg () non sono sincronizzati tra loro e quindi possono essere eseguiti contemporaneamente.

Se non si implementa g () come segue:

g() {
    synchronized(getClass()) {
        ...
    }
}

Trovo questo schema utile anche quando voglio implementare l'esclusione reciproca tra diverse istanze dell'oggetto (che è necessario quando si accede a una risorsa esterna, per esempio).

Dai un'occhiata alla pagina della documentazione di Oracle su Locks and Synchronization

  

Potresti chiederti cosa succede quando viene invocato un metodo sincronizzato statico, poiché un metodo statico è associato a una classe, non a un oggetto. In questo caso, il thread acquisisce il blocco intrinseco per l'oggetto Class associato alla classe . Pertanto l'accesso ai campi statici della classe è controllato da un lucchetto distinto dal lucchetto per qualsiasi istanza della classe .

Un metodo statico ha anche un oggetto associato. Appartiene al file Class.class nel toolkit JDK. Quando il file .class viene caricato nella ram, Class.class crea un'istanza di esso denominata oggetto template.

Ad esempio: - quando si tenta di creare oggetti da una classe di clienti esistente come

Customer c = new Customer();

Il carico di Customer.class nella RAM. In quel momento Class.class nel toolkit JDK crea un oggetto chiamato oggetto Template e carica quel Customer.class nell'oggetto template. I membri statici di quel Customer.class diventano attributi e metodi nell'oggetto template.

Quindi un metodo o un attributo statico ha anche un oggetto

Gli esempi di seguito forniscono maggiore chiarezza tra classe e blocco degli oggetti, la speranza sotto l'esempio aiuterà anche gli altri :)

Ad esempio abbiamo sotto i metodi uno per acquisire la classe e l'altro per acquisire il blocco dell'oggetto:

public class MultiThread {

    public static synchronized void staticLock() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName() + " " + i);
        }
    }

    public synchronized void objLock() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            Thread.sleep(100);
            System.out.println(Thread.currentThread().getName() + " " + i);
        }
    }
}

Quindi, ora possiamo avere i seguenti scenari:

  1. Quando i thread che utilizzano stesso oggetto tentano di accedere allo stesso metodo objLock OR staticLock (ad es. entrambi i thread stanno tentando di accedere allo stesso metodo)

    Thread-0 0
    Thread-0 1
    Thread-0 2
    Thread-0 3
    Thread-0 4
    Thread-1 0
    Thread-1 1
    Thread-1 2
    Thread-1 3
    Thread-1 4
    
  2. Quando i thread che utilizzano stesso oggetto tentano di accedere ai metodi staticLock e objLock contemporaneamente (tenta di accedere a metodi diversi)

    Thread-0 0
    Thread-1 0
    Thread-0 1
    Thread-1 1
    Thread-0 2
    Thread-1 2
    Thread-1 3
    Thread-0 3
    Thread-0 4
    Thread-1 4
    
  3. Quando i thread che utilizzano oggetto diverso tentano di accedere al metodo staticLock

    <*>
  4. Quando i thread che utilizzano oggetto diverso tentano di accedere al metodo objLock

    <*>

Per coloro che non hanno familiarità con il metodo sincronizzato statico bloccato sull'oggetto classe, ad es. per la classe di stringa, String.class mentre il metodo sincronizzato dell'istanza si blocca sull'istanza corrente dell'Oggetto indicata da & # 8220; questo & # 8221; parola chiave in Java. Poiché entrambi questi oggetti sono diversi, hanno un blocco diverso, quindi mentre un thread sta eseguendo un metodo sincronizzato statico, l'altro thread in Java non deve attendere il ritorno di quel thread invece acquisirà un blocco separato indicato con byte .class letterale e entra nel metodo sincronizzato statico.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top