Java >> Java tutorial >  >> Tag >> synchronized

Kan to tråde få adgang til en synkroniseret metode på samme tid?

Kan to tråde få adgang til en synkroniseret metode på samme tid?

Det afhænger af, hvilken objektinstans de to tråde forsøger at låse på. To tråde kan ikke få adgang til den samme synchronized metode på samme objektforekomst. Den ene får låsen, og den anden vil blokere, indtil den første tråd forlader metoden.

I dit eksempel er instansmetoder synkroniseret på det objekt, der indeholder dem. I dette tilfælde, når du ringer til alphonse.bow(...) du låser på alphonse objekt. gaston.bow(...) låser gaston .

Der er et par måder, hvorpå du kan få flere forekomster af et objekt til at låse på det samme objekt.

  • Du kan få metoden til at være static og synchronized i så fald ville de låse på selve klasseobjektet. Der er kun ét af disse objekter pr. klasseindlæser.

    public static synchronized void bow(Friend bower) {
    
  • De kunne begge låse på et defineret statisk objekt. Noget som:

    private static final Object lockObject = new Object();
    ...
    public void bow(Friend bower) {
        synchronized (lockObject) {
            ....
        }
    }
    
  • Eller du kunne passere objektet ind for at låse på, hvis du ikke ville gøre det statisk.

Dit output kunne være noget i stil med følgende:

  1. den gaston tråden (kan) starte først og kalder bow(alphonse)
  2. dette låser gaston objekt og output:Gaston: Alphonse has bowed to me!
  3. den kalder alphonse.bowBack(this) .
  4. dette opkald låser alphonse objekt og output:Alphonse: Gaston has bowed back to me!
  5. alphonse.bowBack(this) afsluttes, og låse alphonse op objekt.
  6. gaston.bow(alphonse) afsluttes, og låse gaston op objekt.
  7. derefter gaston tråden afsluttes.
  8. den alphonse tråden (kan) starte næste gang og kalder bow(gaston)
  9. dette låser alphonse objekt og output:Alphonse: Gaston has bowed to me!
  10. den kalder gaston.bowBack(this) .
  11. dette opkald låser gaston objekt og output:Gaston: Alphonse has bowed back to me!
  12. gaston.bowBack(this) afsluttes, og låse gaston op objekt.
  13. alphonse.bow(gaston) afsluttes, og låse alphonse op objekt.

Dette kan ske i en række forskellige rækkefølger. alphonse tråden kunne køre først, selvom den er start() metode bliver kaldt på et senere tidspunkt. Det eneste, som låsene redder dig fra, er opkaldet til alphonse.bow(...) hvis alphonse.bowBack(...) kører i øjeblikket. Som @user988052 påpegede, fordi hver tråd låser deres eget objekt og derefter forsøger at låse den anden, kan du nemt få en dødvande.


Så kan to tråde få adgang til en synkroniseret metode på samme tid?

Ja og nej:

  • Ja, hvis metoden kaldes på anderledes forekomster af klassen.

  • Nej, to tråde kan ikke kalde synkroniserede metoder på den samme samtidigt forekomst af klassen. Dette er tilfældet, selvom de to tråde kalder forskellige metoder (så længe instansen er den samme).


Jeg tjekkede ikke din kode i detaljer, men jeg tror, ​​jeg genkender den typisk eksempel på, hvordan man skaber en dødvande.

Du bør dog ikke kalde det én gang for at prøve at skabe dødvandet.

Opret tråde i en løkke, og der er meget stor sandsynlighed for, at du får dit dødvande:

for ( int i = 0; i < 1000; i++ ) {
    final Friend alphonse =
        new Friend("Alphonse");
    final Friend gaston =
        new Friend("Gaston");
    new Thread(new Runnable() {
        public void run() { alphonse.bow(gaston); }
    }).start();
    new Thread(new Runnable() {
        public void run() { gaston.bow(alphonse); }
    }).start();
}

Bemærk, at du ikke vil låse dine 2000 tråde fast:kun nogle af dem vil være deadlocked. Du kan bekræfte dette ved at tage en trådump af dit program/JVM.


Java tag