10.07.2015 Views

2× DVD - Vitajte na stránkach www.einsty.hostujem.sk

2× DVD - Vitajte na stránkach www.einsty.hostujem.sk

2× DVD - Vitajte na stránkach www.einsty.hostujem.sk

SHOW MORE
SHOW LESS
  • No tags were found...

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

P R O G R A M U J E M EDruhý spôsob spoèíva v implementácii rozhrania Run<strong>na</strong>ble, ktoré obsahuje metódurun(). Objekt implementujúci toto rozhranie potom môeme zada ako argument kon−štruktora <strong>na</strong> vytvorenie objektu typu Thread. Pri tomto spôsobe sa po zavolaní metódystart() zaène vykonáva metóda run() objektu Run<strong>na</strong>ble. Ukáka:class MyThread implements Run<strong>na</strong>ble{// ...}MyThread mt = new MyThread();Thread tt = new Thread(mt);tt.start();Ako vidno, tentoraz vytvárame dva objekty; jeden typu MyThread (to je ten, ktorý vmetóde run() obsahuje kód nového threadu) a druhý typu Thread – ten funguje ako„obálka“ prvého objektu.Pri vytváraní nového threadu môeme volite¾ne zada jeho meno; to sa môe hodi<strong>na</strong>príklad pri ladení projektu. Okrem toho môeme threadu prideli <strong>sk</strong>upinu, do ktorejbude patri (pozri ïalej).Trieda Thread po<strong>sk</strong>ytuje nieko¾ko ve¾mi potrebných metód. Pomocou metódy yield() sa<strong>na</strong>príklad thread môe vzda procesora. Zavolaním metódy sleep() thread <strong>na</strong> stanovený èas„zaspí“. Násilne preruši thread mono metódou interrupt(). Pomocou metódy join()môeme prikáza aktuálnemu threadu, aby èakal <strong>na</strong> <strong>sk</strong>onèenie iného threadu. Metóda isAlive()indikuje, èi daný thread ije, t. j. èi bol spustený a dosia¾ beí. Názov a prioritu thre−adu zisujeme a <strong>na</strong>stavujeme dvojicami (get|set)Name() a (get|set) Priority().Javov<strong>sk</strong>ý program sa konèí buï explicitným volaním System.exit(), alebo v oka−mihu, keï svoj beh <strong>sk</strong>onèia všetky thready. Pomocou metódy setDaemon() môemevybrané thready premeni <strong>na</strong> „démonov“ (a <strong>na</strong>opak). Systém pri rozhodovaní, èi ukonèiprogram, <strong>na</strong> „démonické“ thready neberie oh¾ad. Metóda run() týchto threadov obyèaj−ne obsahuje nekoneènú sluèku. Na zistenie, èi je vybraný thread démonom, pouijememetódu isDaemon().SKUPINY THREADOV. Thready mono zluèova do <strong>sk</strong>upín, ktoré tvoria stromo−vú štruktúru. Kadá <strong>sk</strong>upi<strong>na</strong> okrem poèiatoènej má pridelenú rodièov<strong>sk</strong>ú <strong>sk</strong>upinu. Privytvorení nového threadu mono urèi, do ktorej <strong>sk</strong>upiny bude thread zaradený.Na reprezentáciu <strong>sk</strong>upiny threadov je urèená trieda ThreadGroup. Pri vytvorení jejmono prideli meno a rodièov<strong>sk</strong>ú <strong>sk</strong>upinu. Ak rodièov<strong>sk</strong>ú <strong>sk</strong>upinu nezadáme, stane saòou automaticky <strong>sk</strong>upi<strong>na</strong>, do ktorej patrí aktuálny thread. Pomocou metódy setMax-Priority() <strong>na</strong>stavujeme maximálnu hodnotu priority, akú môu ma thready patriacedo <strong>sk</strong>upiny. Z ïalších metód vyberáme setDaemon() <strong>na</strong> transformáciu všetkých threa−dov v <strong>sk</strong>upine <strong>na</strong> démonov a <strong>na</strong>opak, interrupt() <strong>na</strong> prerušenie všetkých threadov v<strong>sk</strong>upine, getName(), getParent(), getMaxPriority(), isDaemon(), isDestroyed()<strong>na</strong> zistenie atribútov <strong>sk</strong>upiny èi activeCount()/activeGroupCount() <strong>na</strong> ziste−nie poètu aktívnych threadov a aktívnych <strong>sk</strong>upín patriacich do zadanej <strong>sk</strong>upiny.V súvislosti s threadmi spomeòme ešte triedu ThreadLocal. Táto trieda predstavu−je zvláštny druh objektov, líšiacich sa od bených premenných v tom, e kadý thread,ktorý s nimi pracuje, má k dispozícii vlastnú, nezávisle inicializovanú kópiu. ObjektyThreadLocal zvyèajne bývajú privátnymi statickými zlokami tried, ktoré s threadminejakým spôsobom súvisia.Na èítanie a zápis hodnoty premenných typu ThreadLocal pouijeme metódyget() a set(), ktoré pracujú s typom Object, take uloená hodnota môe by vpodstate ¾ubovo¾ná. Poèiatoèná hodnota premenných je null; ak potrebujeme poui inúinicializaènú hodnotu, musíme si odvodi vlastnú triedu a predefinova chránenú metó−du initialValue().SYNCHRONIZÁCIA. Nevyhnutným dôsledkom zavedenia multita<strong>sk</strong>ingu a multi−threadingu je celkom nová trieda problémov, ktoré v jednopouívate¾<strong>sk</strong>ých a jednoúlo−hových prostrediach prakticky neexistovali. Zoberme si ako príklad dva thready, ktoré pra−cujú s rov<strong>na</strong>kými údajmi. V prípade, e kadý thread èíta a zapisuje údaje bez oh¾adu<strong>na</strong> ten druhý, ¾ahko môe dôjs k <strong>na</strong>rušeniu integrity údajov. Majme <strong>na</strong>sledujúci kód:void run(){for (int i = 0; i < 10; i++)x = x + 1;}Nech oba thready vykonávajú tento kód, ktorého úèelom je desakrát inkrementovapremennú x, ktorá je prístupná obom threadom (<strong>na</strong>príklad je statickým èlenom tej trie−dy, do ktorej patrí metóda run()). Predpokladajme, e poèiatoèná hodnota x je rovnánule. Ak <strong>na</strong>jprv spustíme jeden thread a po jeho <strong>sk</strong>onèení druhý, dostaneme výsledok 20.Nechajme teraz oba thready bea <strong>na</strong>raz. V závislosti od okolností bude lea koneènývýsledok niekde v rozsahu od 10 po 20. Ako je to moné?Jadrom problému je riadok x = x + 1 (zámerne nie je pouitý operátor ++). Privyhodnocovaní tohto výrazu thread <strong>na</strong>èíta obsah premennej x do doèasnej pamäte(registra), zvýši ho v nej o jednotku a uloí <strong>na</strong>spä do hlavnej pamäte. Toto vyhodnote−nie však nie je atomické (nedelite¾né) a v prípade, e threadu vyprší èasové kvantum nie−kde „uprostred“, v premennej x zatia¾ zostane stará hodnota. Druhý thread si odteraz spremennou môe robi, èo chce, jeho úpravy budú onedlho zabudnuté; len èo sa toti kslovu opä dostane prvý thread, dokonèí vyhodnotenie výrazu a prepíše momentálnuhodnotu x v hlavnej pamäti hodnotou, ktorá odpoèívala v pomocnom registri.Poznámka: Je pochopite¾né, e pri praktickej realizácii k opísanému problému vôbecnemusí dôjs. Pouitá implementácia JVM môe vyhodnotenie výrazu vyko<strong>na</strong> atomickyalebo budú okolnosti <strong>na</strong>to¾ko priaznivé, e k iadnej chybe nedôjde. To však vo všeobec−nosti oèakáva nemôeme – vdy treba ráta s <strong>na</strong>jhorším moným prípadom.Programátor, ktorý sa spolieha <strong>na</strong> náhodu, si nezaslúi niè iné, len svoje programy za trestpouíva.Ak chce zvedavý èitate¾ vidie efekt vzájomného „lezenia do kapusty“ <strong>na</strong> vlastné oèi,staèí inkriminovaný výraz rozpísa <strong>na</strong>príklad takto:int x_tmp = x;yield();x = x_tmp + 1;Uvedené tri riadky simulujú vyhodnotenie pôvodného výrazu s vynúteným prepláno−vaním <strong>na</strong> druhý thread medzi <strong>na</strong>èítaním starej a uloením novej hodnoty x. Výslednáhodnota x bude pravdepodobne 10.Tento príklad len jemne <strong>na</strong>z<strong>na</strong>èuje celú sféru problémov, ktoré môu vzniknú pri sú−benej èinnosti viacerých threadov a procesov. Riešenie spoèíva v pouití niektorej zosynchronizaèných metód. Rozsah èlánku, bohuia¾, nedovo¾uje zaobera sa týmitometódami podrobnejšie, pretoe ide o ve¾mi rozsiahlu (ale o to zaujímavejšiu) tému.Pozrime sa preto len <strong>na</strong> monosti, ktoré <strong>na</strong> vyriešenie synchronizaèných problémovpo<strong>sk</strong>ytuje Java.PRÍKAZ synchronized. Úsek kódu, ktorý by sa mal vykonáva atomicky, t. j.maximálne jedným threadom súèasne, <strong>na</strong>zveme v súlade s tradíciami kritickou sekciou.Vylúèi súèasnú prítomnos viacerých threadov v kritickej sekcii je jednoduché: nepovolí−me do nej vstup v prípade, e sa tam <strong>na</strong>chádza iný thread. Je, samozrejme, nevyhnutné,aby thready pred vstupom do kritickej sekcie svoj úmysel dali <strong>na</strong>javo.Existuje mnoho spôsobov, ako zabezpeèi toto tzv. vzájomné vyluèovanie (mutual exclu−sion). Java pouíva zámky (locks) a z nich vychádzajúcu implementáciu monitorov (pozriïalej). Zámok je metaobjekt, ktorý nie je priamo prístupný programátorovi a viae sa vdy <strong>na</strong>existujúci objekt (to, mimochodom, z<strong>na</strong>mená, e pomocou primitívnych typov zamykanemono). Pre kadú kritickú sekciu v programe by mal existova samostatný zámok.Pred vstupom do kritickej sekcie sa thread pokúsi zí<strong>sk</strong>a zámok <strong>na</strong>d vybraným objek−tom. Ak sa mu to podarí, zámok sa uzamkne a thread môe vykonáva kód kritickejoblasti. Ak sa mu to nepodarí, pretoe zámok je u zamknutý, z<strong>na</strong>mená to, e v kritickejoblasti je niekto iný. Thread bude preto pozastavený a opä sa rozbehne a po odo−mknutí zámku. Nevstupuje však do kritickej sekcie automaticky, ale opakuje svoj pokus ozí<strong>sk</strong>anie zámku. Medzi okamihom, keï thread prešiel zo spiaceho stavu do stavu pripra−venosti, a okamihom, keï mu bol pridelený procesor, toti mohol do kritickej sekcie vstú−pi ïalší thread (hoci aj ten istý, èo v nej bol predtým). e to nie je spravodlivé? Nu, vparalelnom prostredí si príliš ne<strong>na</strong>vyberáme…V zdrojovom kóde kritickú sekciu musíme „obali“ do príkazu synchronized. Ten má<strong>na</strong>sledujúcu syntax:synchronized ( v raz ){telo (kritická sekcia)}Výsledkom výrazu musí by nenulová referencia <strong>na</strong> existujúci objekt. Pred zaèatímvykonávania tela príkazu sa thread pokúsi zí<strong>sk</strong>a zámok <strong>na</strong>d týmto objektom. Ako zamy−kací objekt pouijeme niektorý z objektov, s ktorými pracujeme v kritickej sekcii, alebosi vypomôeme pomocným objektom:Object lock = new Object();synchronized (lock){...}Sémantika zamykania objektov v Jave dovo¾uje threadu, ktorý vlastní zámok <strong>na</strong>d neja−kým objektom, zí<strong>sk</strong>a tento zámok ešte raz. To je dôleité <strong>na</strong>príklad v takomto prípade:synchronized (lock){synchronized (lock){// ...}}Thread sa nezasekne <strong>na</strong> druhom príkaze synchronized, ale plynule prejde do kritic−kej sekcie.1/2002 PC REVUE 111

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!