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

Hvad er grunden til, at "synkroniseret" ikke er tilladt i Java 8-grænseflademetoder?

Mens det i første omgang kunne virke indlysende, at man ville ønske at understøtte synchronized modifikator på standardmetoder, viser det sig, at det ville være farligt, og det var derfor forbudt.

Synkroniserede metoder er en forkortelse for en metode, der opfører sig, som om hele kroppen er indesluttet i en synchronized blok, hvis låseobjekt er modtageren. Det kan virke fornuftigt også at udvide denne semantik til standardmetoder; det er jo også instansmetoder med en modtager. (Bemærk at synchronized metoder er udelukkende en syntaktisk optimering; de er ikke nødvendige, de er bare mere kompakte end de tilsvarende synchronized blok. Der er et rimeligt argument at fremføre, at dette var en for tidlig syntaktisk optimering i første omgang, og at synkroniserede metoder forårsager flere problemer, end de løser, men det skib sejlede for længe siden.)

Så hvorfor er de farlige? Synkronisering handler om låsning. Låsning handler om at koordinere delt adgang til foranderlig tilstand. Hvert objekt skal have en synkroniseringspolitik, der bestemmer, hvilke låse der beskytter hvilke tilstandsvariabler. (Se Java Concurrency i praksis, afsnit 2.4.)

Mange objekter bruger Java Monitor-mønsteret som deres synkroniseringspolitik (JCiP 4.1), hvor et objekts tilstand beskyttes af dets iboende lås. Der er intet magisk eller specielt ved dette mønster, men det er praktisk, og brugen af ​​synchronized søgeord om metoder antager implicit dette mønster.

Det er klassen, der ejer staten, der bestemmer objektets synkroniseringspolitik. Men grænseflader ejer ikke tilstanden for de objekter, som de er blandet ind i. Så at bruge en synkroniseret metode i en grænseflade forudsætter en bestemt synkroniseringspolitik, men en som du ikke har noget rimeligt grundlag for at antage, så det kan sagtens være tilfældet, at brugen af ​​synkronisering giver ingen ekstra trådsikkerhed overhovedet (du synkroniserer muligvis på den forkerte lås). Dette ville give dig den falske følelse af tillid til, at du har gjort noget ved trådsikkerheden, og ingen fejlmeddelelse fortæller dig, at du antager den forkerte synkroniseringspolitik.

Det er allerede svært nok konsekvent at opretholde en synkroniseringspolitik for en enkelt kildefil; det er endnu sværere at sikre, at en underklasse korrekt overholder den synkroniseringspolitik, der er defineret af dens superklasse. At forsøge at gøre det mellem sådanne løst koblede klasser (en grænseflade og de muligvis mange klasser, der implementerer den) ville være næsten umuligt og meget udsat for fejl.

I betragtning af alle disse argumenter imod, hvad skulle argumentet være for? Det lader til, at de mest handler om at få grænseflader til at opføre sig mere som karaktertræk. Selvom dette er et forståeligt ønske, er designcentret for standardmetoder grænsefladeevolution, ikke "Træk--". Hvor de to konsekvent kunne opnås, stræbte vi efter at gøre det, men hvor det ene er i konflikt med det andet, måtte vi vælge til fordel for det primære designmål.


Java tag