[Java lista] A synchronized mítosz

Marai Laszlo lists at atleta.hu
2008. Júl. 31., Cs, 12:53:36 CEST


On Thu, 31 Jul 2008 10:03:57 +0200
Friedmann Tamás <friedmannt at tvnetwork.hu> wrote:

  Hali!

> Leginkább azt, hogy a synchronized működése tiszta volt számomra, de a
> volatile egy misztikus kulcsszó, mindenhol elintézik  egy félmondattal.
> ITT: http://www.javaperformancetuning.com/tips/volatile.shtml   van
> idézet pár helyről, hogy mi is a volatile, de hazudnék, ha azt mondanám,
> minden aspektusát értem..

Pedig ott pl. szerintem eleg jol le van riva. A volatile jelentesenek
megertesehez nem art erteni a java memoria modelljet is (JMM), a fenti
linken is van erre egy-ket rejtett utalas.

Teljesitmeny okokbol az egyes threadeknek van egy sajat cache-e, es a
thread altal futtatott kod ezt latja. A synchronized kulcsszo ket dolgot
csinal: egyreszt magahoz ragad egy lock-ot, hogy ezt mas szalak ne
tehessek meg (errol szolt ugye Auth Gabor cikke), masreszt frissiti
a fomemoriabol azokat a valtozokat, amiket sync blokkban levo kod
hasznal. A fomemoria tarolja a valtozok 'igazi' erteket. A blokk vegen
pedig visszakerulnek oda a megvaltozott ertekek. 

Ebbol jol latszik, hogy akkor is rossz eredmenyt fog produkalni egy
program, ha ugy er el egy szalbol tobb valtozot,  hogy valojaban a tobb
szal nem parhuzamosan teszi azt, hanem egymas utan.

A volatile-nak jelolt valtozok viszont a fentiekkel ellentetben sosem a
thread cache-bol jonnek, hanem mindig a fomemoriabol, vagyis
szinkronizalas nelkul is mindig az utolso ervenyes erteket tartalmazzak.
Szerintem eleg keves dologra lehet oket hasznalni, mivel a legtobb
ertelmes algoritmus tobb lepesbol all, tobb lepesben modosit altalaban
tobb valtozot, es altalaban arra van szukseged, hogy ennek az eredmenyet
egyszerre lasd meg (atomicitas). Viszont jo lehet pl. egyszeru
uzenetvaltasra, jelzesre ket szal kozott. Mondjuk van egy szal ami
termeli a feldolgozando adatokat egy masik meg feldolgozza, es mindket
szal tobb objektumon (pl. tobb List-en) dolgozhat. Mondjuk van 64
List-ed (List list[64]), es az egyik szal (producer) pakolja belejuk neha
az adatokat, a masik (consumer) meg olvassa kifele. Megteheted azt is,
hogy mindket szal a list valtozora szinkronizal, de ekkor hatekonytalan
vagy, mert lehet, hogy bizonyos esetekben masik elemevel dolgoznanak,
megis varakoznak egymasra a szalak.

Itt pl. jo megoldas lehet a volatile. Fogsz egy intet, az egyes bitjei
jelolik, hogy a list melyik elemeben (melyik List-ben) van uj adat, es a
feldolgozo szal erre szinkronizal. Ha uj adat erkezik, akkor a producer
szal szinkronizal a list megfelelo elemere, elvegzi az elevegezni
valokat, bebillenti a volatile int megfelelo bitjet, es ertesiti a
feldolgozo szalat, aztan halad tovabb. A feldolgozo szal belenez az
uzenetvaltasra hasznalt int-be, ha abban talal nem nulla bitet, akkor
elokapja az annak megfelelo List-et, szinkronizal ra, es elkezd dolgozni
vele. Ekozben a producer siman dolgozhat a list egy masik elemevel.
(Persze a list-bol a megfelelo elem elovetelenek is szinkronizaltnak kell
lennie!)

Na ez az elmelet, gyakorlatban meg a java.util.concurrent-et
hasznaljuk :), mert konnyu elszurni az ilyen buveszkedeseket, viszont
nehez megtalalni a hibat. Ez annyira igy van, hogy bizonyos
kornyezetekben, programozasi nyelvekben nem is adnak lehetoseget arra,
hogy egy valtozot tobb szlabol erj el, mert ugyis elszurnad, hanem
uzeneteket kell kuldozgetni (masolatot az adataidrol). (Pl. a pythonban
egy darab lock van, amit ha az egyik szal megszerez, akkor az osszes
tobbi blokkolodik, de nem is tervezik ezt olyan szintre elvinni, mint a
javanal, mert az a mondas, hogy message passing-et kell ugyis
alkalmazni.) 

  atleta


További információk a(z) Javalist levelezőlistáról