Pa rhuzamossa g ö A program egyszerre tobb mindent is csinalhat ö Lehet segek: í Szamıtassal egyid ben IO í Tobb processzor: szamıtasok egyid ben í Egy processzor tobb programot futtat (process) ö tobbfelhasznalü s rendszer ö id osztasos technika í Egy program tobb vegrehajtasi szalbü l all (thread) Cel ö Hatekonysag novelese: ha tobb processzor van ö Tobb felhaszna lü kiszolga la sa í egy id ben í interakciü ö Program logikai tagola sa ö az egyik szal a felhasznalü i felulettel foglalkozik ö a masik szal a halü zaton keresztul kommunikal valakivel Alkalmazasi teruletek ö Sza mıta silag nehez problema k ö pl. id jaras-el rejelzes ö Valü s idejú alkalmazasok ö Opera ciü s rendszerek ö Folyamatszabalyoza si feladatok ö Szimulaciü k ö pl. agensek ö Elosztott rendszerek ö pl. repul teri helyfoglalas Pa rhuzamossa gi modellek ö Megosztott (shared) í Tobb processzor, ugyanaz a memü riaterulet ö Elosztott (distributed) í Tobb processzor, mindnek sajat memü ria í Kommunikaciü s csatornak, uzenetkuldes ö Mi van, ha csak egy processzor van? Ha egy processzor van ö A processzor kapcsolgat a kulonboz folyamatok kozott ö Mindegyiket csak kis ideig futtatja ö A pa rhuzamossa g la tszata ö A processzorid jü kihasznala sa í Blokkolt folyamatok nem tartjak fel a tobbit í A valtogata s is id igenyes! 1
Pa rhuzamossa g egy folyamaton belul ö Vegrehajta si sza lak (thread) ö Ilyenekkel fogunk foglalkozni ö Pehelys ly (Lightweight, keves koltsegú) ö Leginka bb a feladat logikai darabola sa bü l í De elkepzelhet, hogy kulonboz processzorokra kerulnek a szalak ö MegosztottÜ jelleg: kozos memü ria Szalak Java-ban ö Beepıtett nyelvi tamogatas: java.lang ö Nyelvi fogalom: (vegrehajtasi) szal, thread ö Tamogatü oszta ly: java.lang.thread Vigya zat! ö Nagyon nehez parhuzamos programot ırni! ö Az ember mar nem latja at ö Sok problema í kommunikaciü í szinkronizaciü í utemezes í interferencia Vegrehajta si sza lak letrehoza sa ö A f program egy vegrehajtasi szal ö Tova bbi vegrehajta si sza lak hozhatü k letre ö Egy Thread osztalyba tartozü objektumot letre kell hozni ö Az objektum start() metü dusa val indıtjuk a vegrehajtasi szalat ö A szal programja az objektum run() metü dusaban van Pelda new Thread(); ö Hat ez meg semmi kulonoset sem csinal, mert ures a run() 2
Pelda (new Thread()).start(); ö Hat ez meg semmi kulonoset sem csinal, mert ures a run() Pelda a run() feluldefinialasara (new MyThread()).start(); class MyThread extends Thread { while(true) System.out.println("Hi!"); Pelda a run() feluldefinialasara (new Thread(){ while(true) System.out.println("Hi!"); ).start(); Az elindıtas ö Nem eleg letrehozni egy Thread objektumot í A Thread objektum nem a vegrehajtasi szal í Csak egy eszkoz, aminek segıtsegevel kulonboz dolgokat csinalhatunk egy vegrehajtasi szallal ö Meg kell hıvni a start() metü dusat ö Ez automatikusan elindıtja a run() metü dust ö Ezt a run()-t kell feluldefinialni, megadni a sza l programja t Illusztra ciü { { { 3
Illusztra ciü { { { Illusztra ciü Illusztra ciü { { { { { { Illusztra ciü Illusztra ciü { { { { { { 4
Illusztra ciü Illusztra ciü { { { { { { Kerdes (new Thread()).start(); ö Hany szalon fut ez a program? Hany vegrehajtasi szal van? Mit csinal ez a program? (new MyThread()).start(); while(true) System.out.println("Bye"); class MyThread extends Thread { while(true) System.out.println("Hi!"); Feladat ö Prü baljuk ki, hogy mit csinal az el z program, de ö legyen harom szal í hozzunk letre ket peldanyt a MyThread osztalybü l í inicializaljuk a ket peldanyt kulonboz stringekkel í ezeket a stringeket kell kiırniuk 5
Mit kene csinalnia? ö Definia latlan ö U temezest l fugg ö A nyelv definıciü ja nem tesz megkotest az utemezesre ö Kulonboz platformokon / virtualis gepeken kulonboz keppen múkodhet ö A virtualis gep meghataroz(hat)ja az utemezesi strategiat ö De azon belul is sok lehet seg van ö Sok mindent l fugg (pl. h merseklett l) U temezes kulonboz platformokon ö Solaris alatt: egy szal addig fut, amıg csak lehet (hatekonyabb) ö NT alatt: id osztasos utemezes (igazsa gosabb) ö O sszefoglalva: ırjunk olyan programokat, amelyek múkodese nem erzekeny az utemezesre Pa rtatlansa g (fairness) ö Ha azt akarjuk, hogy minden szal egyszerreü, parhuzamosanü fusson ö Ha egy szal mar eleg sokatü dolgozott, adjon lehet seget mas szalaknak is yield() ö Ezen metü dus meghıva sa val lehet lemondani a vezerlesr l ö A Thread osztaly statikus metü dusa Mit csinal ez a program? (new MyThread()).start(); while(true){ System.out.println("Bye"); Thread.yield(); Feladat ö Irjuk be a yield()-eket a szalainkba! 6
A masik t ö Java-ban egyszeres orokl des ö Vegrehajta si sza lna l lesza rmaztata s a Thread osztalybü l í elhasznaljaü azt az egy lehet seget ö Megoldas: ne kelljen leszarmaztatni ö Megvalü sıtjuk a Runnable interfeszt, ami el ırja a run() metü dust ö Egy Thread objektum letrehozasanal a konstruktornak atadunk egy futtathatü objektumot Pelda a run() megadasara (new MyThread()).start(); class MyThread extends Thread { while(true) System.out.println("Hi!"); Pelda a run() megadasara (new Thread(new MyRunnable())).start(); class MyRunnable implements Runnable { while(true) System.out.println("Hi!"); Tipikus pelda class MyApplet extends Applet implements Runnable { // animacio megjelenıtese { (new Thread(this)).start(); Letrejott Eletciklus IO rendelkezesre all start() Futtathatü felebredes v. interrupt() yield() JVM notify() wait() Blokkolt sleep() Futü blokkolü IO Veget ert run() elfogy 7
Letrejott start() yield() stop() Veget ert Eletciklus JVM Futtathatü suspend() Futü run() elfogy notify() wait() IO rendelkezesre all felebredes v. interrupt() resume() Blokkolt sleep() blokkolü IO import java.util.*; import java.io.*; class SleepDemo extends Thread { while(true){ try { sleep(1000); catch (InterruptedException ie){ System.out.println(new Date()); public static void main(string[] args) { (new SleepDemo()).start(); while(true){ System.err.println(); import java.util.*; import java.io.*; class BlokkoloDemo extends Thread { while(true){ try { System.in.read(); catch (IOException ie){ System.out.println(new Date()); public static void main(string[] args) { (new BlokkoloDemo()).start(); while(true){ System.err.println(); Feladat ö A mez n (ami a keperny megfelel je) egy ny l es egy rü ka bü klaszik. A nyulat mi iranyıtjuk a szabvanyos bemenetr l az 'q', 'w', 'e', 'a', 's', 'd', 'y', 'x' es 'c' billentyúk segıtsegevel. A rü ka a ny l fele igyekszik. Az allatok a 8 veluk szomszedos mez re lephetnek at egy lepesben. A rü ka kb. ketszer olyan gyakran lep, mint a ny l, viszont minden iranyvaltoztatas el tt meg kell allnia. Szal leallıtasa ö A stop() metü dus nem javasolt. ö Bızzuk ra a szalra, hogy mikor akar megallni. ö Ha a run() egy ciklus, akkor szabjunk neki feltetelt. í Gyakran egy sleep() is van a ciklusban. í A feltetel egy flag-et figyelhet, amit kıvulr l atbillenthetunk. ö Feladat: allıtsuk le a nyuszit, ha megfogta a rü ka! 8
Pelda class MyApplet extends Applet implements Runnable { private boolean fut = false; { public void stop(){ { fut = true; (new Thread(this)).start(); public void stop(){ fut = false; while(fut){ // animacio egy lepese try{ sleep(100); catch(interruptedexeption e){ Az els problema: interferencia ö Ket vagy tobb szal, noha kulon-kulon jü k, egyutt megis butasagot csinalnak: a b = ab V ba í felulırjak egyma s eredmenyeit í inkonzisztenciat okoznak ö Peldaul ket szal ugyanazon az adaton dolgozik egyidejúleg class Szamla { int egyenleg; public void ratesz(int sszeg){ int ujegyenleg; ujegyenleg = egyenleg+ sszeg; egyenleg = ujegyenleg; Interferencia ellen: szinkronizaciü Az adatokhoz valü hozza feres szerializa la sa Kolcsonos kizaras Kritikus szakaszok vedelme ö Szemafor - mint vonatoknal í P es V múvelet í veszelyes programozas, rossz min segú kü d ö Monitor í adatok + múveletek kolcsonos kizarassal í jü l illeszkedik az objektum-elvú szemlelethez ö Irü -olvasü í J-ban nincs olyan nyelvi elem, mint pl. Ada protected Pelda: thread-safeü sza mla class Szamla { private int egyenleg; public synchronized void ratesz(int sszeg){ int ujegyenleg; ujegyenleg = egyenleg+ sszeg; egyenleg = ujegyenleg; 9
A synchronized kulcsszü ö Metü dusok ele ırhatjuk (de pl. interfeszekben nem!) ö Kolcsonos kizaras arra a metü dusra, s t ö Kulcs (lock) + varakozasi sor í A kulcs aze az objektume, amelyike a metü dus í Ugyanaz a kulcs az osszes szinkronizalt metü dusahoz 1 Miel tt egy szal belephetne egy szinkronizalt metü dusba, meg kell szereznie a kulcsot 2 Var ra a varakozasi sorban 3 Kilepeskor visszaadja a kulcsot ö A nyulas-rü kas feladatban hol van szukseg szinkronizaciü ra? Irjuk bele! class Szamla { private int egyenleg; public synchronized void ratesz(int sszeg){ int ujegyenleg; ujegyenleg = egyenleg+ sszeg; egyenleg = ujegyenleg; public synchronized void kivesz(int sszeg) throws SzamlaTullepesException { if( egyenleg < sszeg ) throw new SzamlaTullepesException(); else egyenleg -= sszeg; Szinkronizalt blokkok ö A synchronized kulcsszü vedhet blokk utasıtast is ö Ilyenkor meg kell adni, hogy melyik objektum kulcsan szinkronizaljon synchronized(obj){ ö Metü dus szinkroniza ciü ja val egyenertekú public void ratesz(int sszeg){ synchronized(this){ ö Ha a szamla objektum ratesz metü dusa nem szinkr. synchronized(szamla){ szamla.ratesz(100); Szinkronizalt blokkok (2) ö Sokszor gy hasznaljuk, hogy a monitor szemleletet megtorjuk ö Nem az adat múveleteire biztosıtjuk a kolcsonos kizarast, hanem az adathoz hozza ferni igyekv kü dba tesszuk ö A kritikus szakasz utasıtashoz hasonlıt ö Letjogosultsag: ha nem egy objektumban vannak azok az adatok, amelyekhez szerializalt hozzaferest akarunk garantalni í Er forrasok kezelese, tranzakciü k í Kes bb latunk peldat Statikus szinkronizalt metü dusok class A { static synchronized void m(){ ö Milyen objektum kulcsan szinkronizalunk? ö O nelemzes: az osztalyok futasi idejú reprezentaciü ja a virtualis gepben egy Class osztaly objektum - ezen ö Kerdes: ezek szerint futhatnak egyid ben szinkroniza lt statikus es pelda nymetü dusok? 10
Amikor nem kell szinkronizalni ö Atomi múveletek Java-ban: ertekadas volatile va ltozü knak í a volatile egy mü dosıtü szü í egyesek szerint meg ez sem kell primitıv tıpus valtozü k eseten, kiveve a long es a double valtozü kat ö Ha a jobboldalon nem szerepel a valtozü ö Ha mar tobb valtozü osszefugg (tıpusinvarians), akkor szerializaljuk a hozzaferest synchronized-dal ö Feladat: ez alapjan a nyulaszatbü l kivehet egy par szinkroniza la s wait - notify ö Szigna lokra hasonlıt ö Egy feltetel teljesuleseig blokkolhatja magat egy szal ö A feltetel (potencialis) bekovetkezeset jelezheti egy masik szal ö Alapfeladat: termel - fogyasztü (korlatos) bufferen keresztul kommunikalnak í egy termel, egy fogyasztü í tobb termel, tobb fogyasztü termel Termel -fogyasztü buffer termel() fogyaszt() fogyasztü A termel sza l definıciü ja public class Termel extends Thread { Buffer buffer; public Termel ( Buffer buffer ){ this.buffer = buffer; while(true){ char ch = (char) System.in.read(); buffer.termel(new Character(ch)); A termel sza l definıciü ja public class Termel extends Thread { Buffer buffer; public Termel ( Buffer buffer ){ this.buffer = buffer; while(true){ try{ char ch = (char) System.in.read(); buffer.termel(new Character(ch)); catch ( IOException e ){ 11
Korlatlan buffer, egy fogyasztü public class Buffer extends Sor { public synchronized Object fogyaszt(){ if( űres() ) wait(); return kivesz(); public synchronized void termel(object o){ betesz(o); notify(); Korlatlan buffer, egy fogyasztü public class Buffer extends Sor { public synchronized Object fogyaszt(){ if( űres() ) try{ wait(); catch(interruptedexception e){ return kivesz(); public synchronized void termel(object o){ betesz(o); notify(); Korlatlan buffer, egy fogyasztü public class Buffer extends Sor { public synchronized Object fogyaszt(){ if( űres() ) try{ wait(); catch(interruptedexception e){return null; return kivesz(); public synchronized void termel(object o){ betesz(o); notify(); Múkodes ö Minden objektumhoz tartozik a sima kulcshoz tartozü varakozasi soron kıvul egy masik, az n. wait-va rakoza si sor ö A wait() hatasara a szal bekerul ebbe ö A notify() hatasara az egyik varakozü kikerul bel le ö A wait() es notify() hıvasok csak olyan kü dreszben szerepelhetnek, amelyek ugyanazon az objektumon szinkronizaltak synchronized(obj){ obj.wait(); ö A szal megszerzi az objektum kulcsat, ehhez, ha kell, sorban all egy ideig (synchronized) ö A wait() hatasara elengedi a kulcsot, es bekerul a wait-varakozasi sorba ö Egy masik szal megkaparinthatja a kulcsot (kezd dik a synchronized) ö A notify() metü dussal felebreszthet egy wait-es alvü t, aki bekerul a kulcsos varakozasi sorba ö A synchronized vegen elengedi a kulcsot ö A felebredt alvü nak (is) lehet sege van megszerezni a kulcssot es tovabbmenni ö A synchronized blokkja vegen is elengedi a kulcsot 12
Korlatlan buffer, tobb fogyasztü public class Buffer extends Sor { public synchronized Object fogyaszt(){ while( űres() ) try{ wait(); catch(interruptedexception e){ return kivesz(); public synchronized void termel(object o){ betesz(o); notifyall(); Nincs szukseg busy waiting-re Feladatok ö Fejezzuk be a termel -fogyasztü feladatot a fogyasztü implementa lasa val ö Hogyan valü sıtanank meg a szemaforokat Java-ban? ö Es az ırü -olvasü problema t? ö Javıtsunk a nyulas-rü kas programunkon! A keperny re akkor kell kirajzolni a mez t, ha valami valtozas tortent Sza lak kommunika ciü ja ö Aszinkron leginka bb ö Szinkron kommunikaciü (pl. Ada randev ) helyett csak wait-notify szinkronizaciü van ö Megosztott es elosztott szemlelet egyarant ö Megosztott: kozos memü rian keresztul ö Elosztott: uzenetkuldes csatornakkal (Piped csatornak) ö Termel -fogyasztü Kozos memü rian keresztul ö A kommunika ciü ra haszna lt objektumokra referenciakat lehet atadni, eljuttatni a szalakba í pl. a rü ka a ny lrü l ıgy szerez informaciü t ö Vegletes esetben magat a futtathatü objektumot is megoszthatjuk: class A implements Runnable { // adatok, mᑺveletekkel A a = new A(); Thread t1 = new Thread(a); Thread t2 = new Thread(a); Piped csatornaosztalyok ö PipedInputStream, PipedOutputStream PipedReader, PipedWriter ö Egy bemenetit es egy kimenetit osszekapcsolunk ö A cs egyik vegere az egyik szal ır, a cs masik veger l a masik szal olvassa ö Vigya zat: az olvasa s blokkolü múvelet! í available(), ready() - bar ez utü bbival rosszak a tapasztalatok 13
PipedReader r = new PipedReader(); PipedWriter w = new PipedWriter(r); (new Termel Szal(w)).start(); (new FogyasztoSzal(w)).start(); public class Termel Szal extends Thread { Writer w; public Termel Szal( Writer w ){ this.w = w; while(fut){ char adat = // termel w.write(adat); w.flush(); Holtpont (deadlock) ö Nehany folyamat veglegesen blokkolü dik, arra varnak, hogy egy masik, szinten a holtpontos halmazban lev folyamat csinaljon valamit ö Az interferencia tokeletes kikuszobolese :-) ö T l sok a szinkronizaciü ö Gyakran er forra s-kezeles vagy tranzakciü k kozben ö Pelda: etkez filozü fusok (dining philosophers) Mit lehet tenni? ö Nincs univerzalis megoldas, a programozü dolga a feladathoz illeszked megoldas kidolgozasa ö Detektalas, megszuntetes (pl. timeout), el rejelzes, megel zes ö Megel zes: er forra sok sorrendbe a llıta sa, szimmetria megtorese, kozponti iranyıtas, veletlenszerú varakoztatas, stb. í pl. a filozü fusok class A { synchronized void m1(){ synchronized void m2(b b){ b.m1() class B { synchronized void m1(){ synchronized void m2(a a){ a.m1() A a = new A(); B b = new B(); class A { void m1(){ void m2(b b){ b.m1() class B { void m1(){ void m2(a a){ a.m1() A a = new A(); B b = new B(); Object o = new Object(); Egyik szalban Masik szalban a.m2(b); b.m2(a); Egyik szalban Masik szalban synchronized(o) {a.m2(b); synchronized(o) {b.m2(a); 14
Kieheztetes (starvation, livelock) ö A rendszer nem all le, a folyamatok mennek, de van olyan koztuk, amelyik nem tudja azt csinalni, amit szeretne ö Pl. tobb fogyasztü kozul az egyik el van hanyagolva. Vagy az egyik filozü fus sosem eszik. ö Amikor a folyamatra kerul a vezerles, kezd futni, de akkor epp nem teljesul a tovabbhaladasi feltetel ö Konnyen bekovetkezhet wait-notify mellett ö Kivedes/megel zes meg nehezebb, mint a holtpont eseten Priorita s ö A szalakhoz prioritas van rendelve ö Prioritasi szintek: 1 (MIN_PRIORITY) es 10 (MAX_PRIORITY) kozott í Rendszerszintú szalak prioritasa 11 ö A Java a prioritasi szintek kozott preemptıv utemezest ker: a magasabb prioritas futhat í Sajnos a JVM-nek nem kotelez ezt betartania í Ne ezen m ljon a programunk helyessege ö Egy szinten belul definialatlan í SUN GreenÜ szalak: kooperatıv í SUN NatıvÜ szalak: preemptıv Prioritas (folyt.) ö Ha egy szal futtathatü va valik (pl. felebred vagy elindul), es egy alacsonyabb prioritas fut eppen, akkor az atadja a vezerlest ö Prioritasi szint lekerdezese es beallıtasa: int getpriority() void setpriority(int priority) ö Szal letrehozasakor a letrehozott orokli a letrehozü prioritasat, ha mast nem adunk meg ö A ltala nos strategia: sokat dolgozü sza lnak kisebb prioritast erdemes adni Sza lcsoportok ö A sza lak sza lcsoportokba sorolhatü k í Szal letrehozasakor ö java.lang.threadgroup ö Logikailag osszetartozü szalak lehetnek egy csoportban ö A csoport maximalis prioritasa beallıthatü, a csoportbeli szalake ezt nem fogja meghaladni ö A szalak lekerdezhetnek informaciü kat a sajat csoportjukrü l ö A sza lcsoportok hierarchia ba szervezhet k Demonok ö Szalak lehetnek demonok ö Ha a nem demon szalak veget ernek, akkor a program is veget er, es a demon szalak a hatterben futnak tovabb ö Az elindıtas, azaz a start() el tt be kell allıtani boolean isdaemon() void setdaemon(boolean on) Meg nehany múvelet ö join() A futü szal blokkolü dik, amıg az a szal veget nem er, amelyiknek a join-jat meghıvta í id korlat adhatü meg ö interrupt() Egy blokkolt allapot szalat (sleep, wait) felebreszt. A felebredt szalban a blokkolü utasıtas helyen InterruptedException lep fel ö stop(), suspend() es resume() Elavultak, mert veszelyesek (helyesseg, holtpont) 15