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

Hvorfor er synkroniseret blok bedre end synkroniseret metode?

Det er ikke et spørgsmål om bedre, bare anderledes.

Når du synkroniserer en metode, synkroniserer du effektivt med selve objektet. I tilfælde af en statisk metode synkroniserer du med objektets klasse. Så de følgende to stykker kode udføres på samme måde:

public synchronized int getCount() {
    // ...
}

Det er ligesom du skrev dette.

public int getCount() {
    synchronized (this) {
        // ...
    }
}

Hvis du vil kontrollere synkronisering til et bestemt objekt, eller du kun vil have del af en metode, der skal synkroniseres med objektet, og angiv derefter en synchronized blok. Hvis du bruger synchronized nøgleord på metodeerklæringen, vil det synkronisere hele metoden til objektet eller klassen.


Selvom det normalt ikke er et problem, er det fra et sikkerhedsperspektiv bedre at bruge synkroniseret på et privat objekt i stedet for at sætte det på en metode.

At sætte det på metoden betyder, at du bruger låsen på selve objektet til at give trådsikkerhed. Med denne form for mekanisme er det muligt for en ondsindet bruger af din kode også at få låsen på dit objekt og holde den for evigt, hvilket effektivt blokerer andre tråde. En ikke-ondsindet bruger kan effektivt gøre det samme utilsigtet.

Hvis du bruger låsen på et privat datamedlem, kan du forhindre dette, da det er umuligt for en ondsindet bruger at få låsen på dit private objekt.

private final Object lockObject = new Object();

public void getCount() {
    synchronized( lockObject ) {
        ...
    }
}

Denne teknik er nævnt i Bloch's Effective Java (2nd Ed), Item #70


Forskellen er, hvilken lås der erhverves:

  • synkroniseret metode erhverver en lås på hele objektet. Det betyder, at ingen anden tråd kan bruge nogen synkroniseret metode i hele objektet, mens metoden køres af én tråd.

  • synkroniserede blokke erhverver en lås i objektet mellem parenteser efter det synkroniserede nøgleord. Det betyder, at ingen anden tråd kan opnå en lås på det låste objekt, før den synkroniserede blok forlader.

Så hvis du vil låse hele objektet, skal du bruge en synkroniseret metode. Hvis du vil holde andre dele af objektet tilgængelige for andre tråde, skal du bruge synkroniseret blok.

Hvis du vælger det låste objekt med omhu, vil synkroniserede blokeringer føre til mindre strid, fordi hele objektet/klassen ikke er blokeret.

Dette gælder på samme måde for statiske metoder:en synkroniseret statisk metode vil erhverve en lås i hele klasseobjektet, mens en synkroniseret blok inde i en statisk metode vil erhverve en lås i objektet mellem parenteser.


Java tag