P|||Q 812315A Ohjelmiston rakentaminen. Asynkronisuus Ari Vesanen ari.vesanen (at) oulu.fi P|||Q Yleistä moduulista Tällä kertaa sisältää Java-kielistä monisäieohjelmointia Suoritustapa: Neljästä ohjelmointitehtävästä valitaan kaksi, joihin laaditaan ratkaisut Arvostellaan 1-5, loppuarvosana keskiarvo mahdollisesti ylöspäin pyöristettynä Suositellaan tekemään Javalla, C++ mahdollinen, muista kielistä sovittava erikseen Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 2 P|||Q Moduulin aikataulu Aloitusseminaari 16.6. klo 10-16 Lyhyt johdanto rinnakkaisuuteen ja Java-kielen monisäieohjelmointiin Rinnakkaisuuden piirteitä ja ohjelmointitehtäviä Suoritettavien tehtävien läpikäynti 17.6. – 4.8. Kiivasta ohjelmointia ja tehtävien palautus viimeistään 4.8 Jokainen palauttaa omat ratkaisut Lopetusseminaari 5.8. klo 10 - 16 Käydään läpi ratkaisut ja vertaillaan niitä toisiinsa Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 3 P|||Q Moduulin sisältö I. Johdanto rinnakkaisuuteen II. Javan rinnakkaisuuden perustoteutus III. Rinnakkaisen ohjelmoinnin malleja IV. Eloisuusongelmista V. Edistyneempi Javan rinnakkaisuus VI. Tehtävät Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 4 P|||Q Kirjallisuutta Goetz, B. et al.: Java Concurrency in Practice, Addison-Wesley 2010 González, J.: Java 7 Concurrency Cookbook. Packt Publishing 2012. Hartley, S.: Concurrent Programming, The Java Programming Language, Oxford University Press Inc. 1998 Lea, D.: Concurrent Programming in Java, design Principles and Patterns Second Edition, Addison-Wesley 2000 Kaksi viimeistä ennen Java 5.0:aa Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 5 P|||Q WWW-lähteitä Javan API-dokumentaatio: https://docs.oracle.com/javase/8/docs/api/ Oraclen Java-tutoriaali http://docs.oracle.com/javase/tutorial/essential/concurrency Muita Java-tutoriaaleja http://www.tutorialspoint.com/java/java_multithreading.htm http://tutorials.jenkov.com/java-concurrency/index.html Aalto-yliopiston kurssi https://noppa.aalto.fi/noppa/kurssi/t-106.5600/luennot Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 6 P|||Q I Johdanto rinnakkaisuuteen Peräkkäinen Käskyt suoritetaan peräkkäin Yksikäsitteinen suorituspolku Deterministinen sama syöte, sama tulos aina Ari Vesanen, Tietojenkäsitttelytieteiden laitos vs. Rinnakkainen Toimintoja suoritetaan rinnakkain Ei selvää suorituspolkua Epädeterministinen tulos voi riippua suoritusjärjestyksestä 812315 Ohjelmiston rakentaminen, Asynkronisuus 7 P|||Q I.1 Prosessit ja säikeet Prosessi Tapa ajaa useita ohjelmia rinnakkain yhdessä prosessorissa Oma muistialue Kommunikointi esim. putkilla tai socketeilla Säie Prosessia kevyempi Prosessi voidaan jakaa säikeisiin Säikeellä oma ohjelmalaskuri ja pino Säikeet jakavat prosessin muistialueen ja resurssit Tässä moduulissa monisäieohjelmointia Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 8 P|||Q I.2 Rinnakkaisen ohjelman oikeellisuuskriteerit Turvallisuus (safety) Oliot ja muuttujat pysyvät kunnossa Eloisuus (liveness) Kaikki aiotut operaatiot suoritetaan joskus Turvallisuus: Ei-atomaarinen operaatio voi epäonnistua jos kaksi säiettä toimii yhtä aikaa -> Metodi voi toimia väärin jos sitä kutsutaan kahdesta säikeestä Säieturvallinen (thread safe): toimii oikein millä tahansa kutsujärjestyksellä Resurssin käsitteleminen kahdesta säikeestä samanaikaisesti = kilpailutilanne (race condition) Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 9 P|||Q I.2 Rinnakkaisen ohjelman oikeellisuuskriteerit Eloisuus: Aiotut operaatiot suoritetaan – ei aikarajaa Reaaliaikainen ohjelmointi – asetetaan aikarajoja Turvallisuus ja eloisuus jossain määrin vastakkaisia Ongelmatilanteisiin varauduttava suunnitteluvaiheessa Ohjelman debuggaus erittäin vaikeaa (lokitiedoston kirjoitus usein auttaa) Ohjelman täydellinen testaus mahdotonta Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 10 P|||Q II Javan rinnakkaisuuden perustoteutus Java alkujaan suunniteltu tukemaan rinnakkaisuutta Olio-ohjelmoinnin ja Javan perusteet oletetaan tunnetuksi Javan virtuaalikone (JVM) suorittaa Java-ohjelman huolehtii myös rinnakkaisuudesta Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 11 P|||Q II.1. Javan säikeet Käyttäjäsäikeet (user threads) varsinaiset säikeet Taustasäikeet (daemon threads) toimivat taustalla Ohjelma loppuu, kun sen kaikki käyttäjäsäikeet päättyvät tai kutsutaan Runtime luokan exit()-metodia (koodissa System.exit(0);) Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 12 P|||Q II.1. Javan säikeet. Säikeen tilat Uusi (NEW) Säie on luotu, ei voi vielä toimia Ajettava (RUNNABLE) Säie voi toimia, kun saa suoritusaikaa Estetty (BLOCKED) Toiminta on estetty, koska odottaa lukon vapautumista Odottaa (WAITING) Säie odottaa toisen säikeen operaatiota Odottaa ajastetusti (TIMED_WAITING) Kuten yllä tai kun annettu aika on kulunut Lopetettu, kuollut (TERMINATED) Säikeen suoritus on loppunut Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 13 P|||Q II.1. Javan säikeet. Säikeen luominen 1. 2. 3. Kirjoita luokka, joka perii Thread-luokan run()-metodi uudelleenmääriteltävä TAI Kirjoita luokka joka toteuttaa Runnable –rajapinnan toteutettava run()-metodi Säikeen suorittaminen: Luo uusi Thread-olio Konfiguroi (ei pakollinen) Anna prioriteetti ja nimi Käynnistä kutsumalla start()-metodia Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 14 P|||Q II.1. Javan säikeet. Säikeen luominen (2) HUOM1: Käynnistys kutsumalla startia, toiminnallisuus runissa! HUOM2: Säie päättyy, kun run loppuu Testaa ohjelmia Basicthreads.java BasicRunnable.java Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 15 P|||Q II.1. Javan säikeet. Säikeen lopettaminen Säie päättyy kun run loppuu Suositeltavin tapa säikeen keskeyttämiseen: interrupt asettaa säikeen keskeytystilaan, ei lopeta suoritusta tutki onko keskeytetty (metodi isInterrupted()) myös interrupted() - nollaa keskytystilan Nukkuvan tai odottavan säikeen keskeyttäminen aiheuttaa poikkeuksen InterruptedException säie ei ajossa -> ei voi suoraan keskeyttää ko. poikkeus on aina käsiteltävä kun tehdään wait tai sleep Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 16 P|||Q II.1. Javan säikeet. Säikeen lopettaminen //Määritellään säieluokka class Interruptible extends Thread{ public void run(){ while(!this.isInterrupted()){ // Tee jotain} // Lopputoimenpiteet } } //Pääohjelmassa koodi: Interruptible irThread = new Interruptible(); irThread.start(); // Toimenpiteitä pääohjelmassa // Lopetetaan irThread irThread.interrupt(); Tehtävä ThreadInterrupt.java Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 17 P|||Q II.2. Javan säikeiden synkronointi 1. 2. Oikean toiminnan varmistamiseksi kahdenlaista synkronointia Kilpailun synkronointi Tarvitaan kun resurssia käytetään monesta säikeestä Yhteistoiminnan synkronointi Tarvitaan kun säikeen toiminta riippuu toisen säikeen toiminnasta Javan perusmekanismi monitori = olio, jolla on lukko ja odotusjoukko Mikä tahansa Javan olio voi olla monitori Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 18 P|||Q II.2.1 Javan monitorin toiminta SP. JOUKKO SÄIE 5 SÄIE 6 Odotusjoukko (wait set) = ne säikeet jotka odottavat ilmoitusta (notify()) kutsuttuaan wait() – metodia METODI1 SÄIE 1 METODI2 Sisäänpääsyjoukko LOHKO1 SÄIE 3 SÄIE 2 SÄIE 4 (entry set) = säikeet, jotka odottavat pääsyä monitoriin ensimmäistä kertaa ODOTUSJOUKKO Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 19 P|||Q II.2.2 Kilpailun synkronointi Lukko otetaan haltuun kutsumalla synchronizedavainsanalla merkittyä metodia (tai koodilohkoa) olion kaikkien synkronoitujen metodien ja lohkojen suorittaminen estyy kunnes säie luopuu lukosta Lukosta luopuminen: Synkronoitu metodi/lohko loppuu Säie siirtyy odotustilaan HUOM! Thread.sleep(); ei aiheuta lukosta luopumista. Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 20 P|||Q II.2.2 Kilpailun synkronointi (2) ESIM: Seuraavat yhtäpitävät: synchronized void f(){ // Metodin runko } void f(){ synchronized(this){ // Metodin runko } } Tehtävä: Poista kilpailutilanne ohjelmista RaceCondition.java ja UnsafeTicketOffice.java Optimoi synkronointi jälkimmäisessä Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 21 P|||Q II.2.3 Yhteistoiminnan synkronointi Säikeessä voidaan odottaa toisen säikeen päättymistä kutsumalla sen join()-metodia Monitorin odotusjoukkoon voidaan vaikuttaa metodeilla wait(): asettaa kutsuvan säikeen odotustilaan notify(): vapauttaa yhden odottavan säikeen notifyAll(): vapauttaa kaikki odottavat säikeet Kaikkien em. metodien kutsumiseksi on oltava hallussa monitorin lukko Vapautetut säikeet kilpailevat normaaliin tapaan monitorin lukosta Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 22 P|||Q II.2.3 Yhteistoiminnan synkronointi (2) Jos odottava säie keskeytetään, syntyy InterruptedException Käsiteltävä, jos kutsutaan wait()-metodia Tehtävä: Ohjelmassa PingPongEx.java kaksi säiettä kutsuu luokan PingPongController metodeja, jotka tulostavat sanat ”PING” ja ”PONG” Synkronoi luokka PingPongController niin, että sanat tulostetaan aina vuorotellen. Metodeissa esiintyviä sleep-aikoja ei saa muuttaa Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 23 P|||Q III Rinnakkaisen ohjelmoinnin malleja III.1 Tuottaja-kuluttajamalli Soveltuu moneen rinnakkaisen ohjelmoinnin ongelmaan Kahdentyyppisiä säikeitä (tai prosesseja): Tuottajat Luovat uusia olioita (dataa) Kuluttaja Käsittelevät tuottajien luomia olioita Olioiden varastona voidaan käyttää esim. synkronoitua syklistä puskuria: Huolehdittava, että vain yksi säie käsittelee puskuria Huolehdittava että täyteen puskuriin ei kirjoiteta Huolehdittava että tyhjästä puskurista ei lueta Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 24 P|||Q III.2 Lukija-kirjoittajamalli Alunperin mallinsi tietokannan toimintaa Yleishyödyllinen rinnakkaisessa ohjelmoinnissa Voidaan käyttää säätelemään pääsyä monenlaisiin resursseihin Kahdenlaisia säikeitä: lukijasäikeet ja kirjoittajasäikeet resurssia saa lukea moni säie yhtä aikaa resurssia voi päivittää vain yksi (kirjoittaja)säie resurssia ei saa lukea jos kirjoitetaan Abstrakti luokka ReadAndWRite mallintaa toimintaa, operaatiot readOperation() ja writeOperation() määriteltävä perivässä luokassa Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 25 P|||Q IV Eloisuusongelmat Lukkiutuminen (deadlock) Yleinen syy säikeiden jumittumiseen Säikeet odottavat ristiin toistensa lukitsemien resurssien vapautumista Uloslukkiutuminen Koodi voi sisältää sisäkkäisiä olioita joilla synkronoituja metodeja -> Säie voi lukita itsensä ulos Menetetty signaali Säie odottaa signaalia, joka on tuotettu ennen kuin säie alkoi odottaa Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 26 P|||Q V Javan edistyneempi rinnakkaisuuden hallinta Javan versioon 5.0 lisätukea rinnakkaisuuden hallintaan java.util.concurrent java.util.concurrent.locks java.util.concurrent.atomic Em. Pakkaukset sisältävät Erilaisia synkronointiprimitiivejä, Rinnakkaisessa ohjelmoinnissa käyttökelpoisia kokoelmia, Säieturvallisia muuttujatyyppejä Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 27 P|||Q V.1 Semaforit Semafori: kokonaislukumuuttuja, jonka arvo on lupien lukumäärä Säie pyytää lupaa semaforilta: Jos arvo suurempi kuin nolla, säie saa luvan ja arvoa vähennetään Jos arvo nolla, säie jää odottamaan, kunnes lupien määrä kasvaa Kun säie luopuu luvasta, semaforin arvoa kasvatetaan Voidaan käyttää poissulkevuuteen tai synkronoituna laskurina Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 28 P|||Q V.1 Semaforit (2) Javassa semafori luokka Semaphore, pakkauksessa java.util.concurrent Käyttö: // Luodaan semafori, jolla alussa yksi lupa Semaphore sema = new Semaphore(1); // Luvan pyytäminen sema.acquire(); // Luvan vapauttaminen sema.release(); Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 29 P|||Q V.2 Lukot ja ehtomuuttujat Pakkauksessa java.util.concurrent.locks rajapinta Lock Erilaisia implementointeja -> perussynkronointia monipuolisempi toteutus Lukkoihin voidaan liittää Condition-rajapinnan toteuttavia olioita vastaamaan ehtomuuttujia Käyttöidiomi kilpailun synkronoinnille Lock lukko = ...; // Sopiva lukko-olio lukko.lock(); try { // Käytä lukon suojaamaa resurssia } finally { lukko.unlock(); // Varma vapauttaminen } Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 30 P|||Q V.2 Lukot ja ehtomuuttujat (2) Luokan ReentrantLock olio Javan monitorin yleistys Olioon voi liittyä useita ehtomuuttujia (Condition), luodaan luokan metodilla newCondition() Condition-olion odotusmetodi await() ja ilmoitusmetodit signal() sekä signalAll() Vastaavat Object-luokan metodeja wait(), notify() sekä notifyAll() Katso esimerkkiohjelmista CircularBufferWithLocks.java Tehtäviä: Poista ohjelmista RaceConditionRunnable.java ja UnsafeTicketOffice.java kilpailutilanne lukkoja käyttämällä. Muuta aiemmin tehty PingPong-ohjelma käyttämään lukkoja. Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 31 P|||Q V.3 Suorittajat ja säievarastot Javan pakkaukseen java.util.concurrent sisältyy rajapinta Executor, jonka avulla voidaan eristää tehtävän välitys ja sen suoritusmekanismi toisistaan. Metodi void execute(Runnable r) Toteuttamalla rajapinta saadaan erilaisia suorittajia Luokissa voidaan käyttää Executor-oliota ja sitoa se vasta myöhemmin tietyntyyppiseen suorittajaan, esim class SimpleExecutor implements Executor{ public void execute(Runnable r){ new Thread(r).start(); } } Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 32 P|||Q V.3.1 Säievarastot Kiinteä määrä säikeitä, joille annetaan tehtäviä suoritettavaksi Vähentää tarvittavien säikeiden määrää, jos tehtävien ei tarvitse olla yhtä aikaa ajossa Javan luokka ThreadPoolExecutor Olio saadaan kutsumalla Executors-luokan staattista metodia newFixedThreadPool(int poolSize) Tehtävä käynnistetään luokan metodilla execute -> pääsee suoritukseen kun varaston säie vapautuu Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 33 P|||Q V.3.1 Säievarastot (2) Javan luokka ThreadPoolExecutor jatkuu Luokan metodi shutdown() -> tehtävät ajetaan loppuun, uusia ei oteta Luokan metodi awaitForTermination() odottaa kunnes kaikki tehtävät suoritettu Ks. esimerkit NQueensWithPool.java ja NQueensWithPoolLatch.java Tehtävä: Jälkimmäisessä CountDownLatch odottaa tehtävien valmistumista. Korvaa se semaforilla. Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 34 P|||Q VI Tehtävät 1. 2. 3. 4. Jokainen palauttaa oman ratkaisun Seuraavista neljästä tehtävästä valitaan kaksi Kuvaukset erillisessä dokumentissä Boolimaljasimulaatio Kanjonia ylittävät turistit Huvipuiston vuoristorata Neljä samaa numeroa -peli Ari Vesanen, Tietojenkäsitttelytieteiden laitos 812315 Ohjelmiston rakentaminen, Asynkronisuus 35
© Copyright 2024