Liite 1. Projektin tulokset (Semaforit Javassa) Jukka Hyvärinen Aleksanteri Aaltonen

Samankaltaiset tiedostot
Rinnakkaisohjelmointi, Syksy 2006

Rinnakkaisohjelmointi kurssi. Opintopiiri työskentelyn raportti

Monitorit -projekti Rinnakkaisohjelmointi

Projekti 1 Säikeet ja kriittisen vaiheen kontrollointi javalla

Javan semaforit. Joel Rybicki, Aleksi Nur mi, Jara Uitto. Helsingin yliopisto

Ohjelmoinnin peruskurssien laaja oppimäärä

Luento 6. T Ohjelmoinnin jatkokurssi T1 & T Ohjelmoinnin jatkokurssi L1. Luennoitsija: Otto Seppälä

Käyttöjärjestelmät: poissulkeminen ja synkronointi

Tehtävä 1. Tehtävä 2. Arvosteluperusteet Koherentti selitys Koherentti esimerkki

Semaforit Javassa. Mari Kononow, Eveliina Mattila, Sindi Poikolainen HELSINGIN YLIOPISTO

Jaana Diakite Projekti 1 JAVA-Monitorit 1(13) Rinnakkaisohjelmointi Anu Uusitalo

Johdatus Java 1.5:n semaforeihin

812315A Ohjelmiston rakentaminen. Asynkronisuus

Ohjelmoinnin jatkokurssi, kurssikoe

Olio-ohjelmointi Javalla

Mikä yhteyssuhde on?

10 Lock Lock-lause

8. Näppäimistöltä lukeminen 8.1

Sisältö Johdanto. Tiedostojen lukeminen. Tiedostojen kirjoittaminen. 26.2

11. Javan toistorakenteet 11.1

Oppimistavoitteet kurssilla Rinnakkaisohjelmointi

Ohjelmointitaito (ict1td002, 12 op) Kevät Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen

Kompositio. Mikä komposition on? Kompositio vs. yhteyssuhde Kompositio Javalla Konstruktorit set-ja get-metodit tostring-metodi Pääohjelma

12. Javan toistorakenteet 12.1

Ohjelmointi 2 / 2010 Välikoe / 26.3

815338A Ohjelmointikielten periaatteet Harjoitus 5 Vastaukset

9. Periytyminen Javassa 9.1

Sisältö. Johdanto. Tiedostojen lukeminen. Tiedostojen kirjoittaminen. 6.2

12. Javan toistorakenteet 12.1

Periytyminen (inheritance)

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op. Poikkeukset ja tietovirrat: Virhetilanteiden ja syötevirtojen käsittely

JReleaser Yksikkötestaus ja JUnit. Mikko Mäkelä

Metodit. Metodien määrittely. Metodin parametrit ja paluuarvo. Metodien suorittaminen eli kutsuminen. Metodien kuormittaminen

8. Näppäimistöltä lukeminen 8.1

Palvelut. Sulautetut järjestelmät Luku 2 Sivu 1 (??) Sulautetut käyttöjärjestelmät

Rajapinta (interface)

JAVA on ohjelmointikieli, mikä on kieliopiltaan hyvin samankaltainen, jopa identtinen mm. C++

RINNAKKAINEN OHJELMOINTI A,

4. Luokan testaus ja käyttö olion kautta 4.1

Ohjelmoinnin perusteet, kurssikoe

1 Tehtävän kuvaus ja analysointi

Luokka Murtoluku uudelleen. Kirjoitetaan luokka Murtoluku uudelleen niin, että murtolukujen sieventäminen on mahdollista.

812341A Olio-ohjelmointi Peruskäsitteet jatkoa

Sisältö. Johdanto. Tiedostojen lukeminen. Tiedostojen kirjoittaminen. 6.2

Oliosuunnitteluesimerkki: Yrityksen palkanlaskentajärjestelmä

14. Poikkeukset 14.1

Graafisen käyttöliittymän ohjelmointi Syksy 2013

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

58131 Tietorakenteet ja algoritmit (syksy 2015)

Tietorakenteet (syksy 2013)

Java kahdessa tunnissa. Jyry Suvilehto

Poikkeustenkäsittely

Luokan sisällä on lista

Ohjelmointi 2 / 2008 Välikoe / Pöytätestaa seuraava ohjelma.

Jypelin käyttöohjeet» Miten saan peliin pistelaskurin?

Monitorit. Monitori Synkronointimenetelmiä Esimerkkejä. Andrews , Stallings 5.5

Monitorit. Tavoite. Monitori Synkronointimenetelmiä Esimerkkejä. Andrews , Stallings 5.5. Minimoi virhemahdollisuuksia

Metodien tekeminen Javalla

Yleistä. Nyt käsitellään vain taulukko (array), joka on saman tyyppisten muuttujien eli alkioiden (element) kokoelma.

9. Periytyminen Javassa 9.1

JAVA-OHJELMOINTI 3 op A274615

Sisällys. 11. Javan toistorakenteet. Laskurimuuttujat. Yleistä

T Henkilökohtainen harjoitus: FASTAXON

JAVA-PERUSTEET. JAVA-OHJELMOINTI 3op A JAVAN PERUSTEET LYHYT KERTAUS JAVAN OMINAISUUKSISTA JAVAN OMINAISUUKSIA. Java vs. C++?

Sisällys. 12. Näppäimistöltä lukeminen. Yleistä. Yleistä

Luokat ja oliot. Ville Sundberg

Javan perusteita. Janne Käki

Ohjelmointitaito (ict1td002, 12 op) Kevät Java-ohjelmoinnin alkeita. Tietokoneohjelma. Raine Kauppinen

Vertailulauseet. Ehtolausekkeet. Vertailulauseet. Vertailulauseet. if-lauseke. if-lauseke. Javan perusteet 2004

OSA I: Yhteisten muuttujien käyttö Prosessit samassa koneessa. Sisältöä. Poissulkeminen. Halutut ominaisuudet 2-1. Rinnakkaiset, atomiset operaatiot

Listarakenne (ArrayList-luokka)

Rinnakkaisuus. parallel tietokoneissa rinnakkaisia laskentayksiköitä concurrent asioita tapahtuu yhtaikaa. TTY Ohjelmistotekniikka

7. Oliot ja viitteet 7.1

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Taulukot & Periytyminen

14. Poikkeukset 14.1

Sisällys. 14. Poikkeukset. Johdanto. Johdanto

Sisältö. 22. Taulukot. Yleistä. Yleistä

Olion elinikä. Olion luominen. Olion tuhoutuminen. Olion tuhoutuminen. Kissa rontti = null; rontti = new Kissa();

Informaatioteknologian laitos Olio-ohjelmoinnin perusteet / Salo

Ohjelmointikielet ja -paradigmat 5op. Markus Norrena

ITKP102 Ohjelmointi 1 (6 op)

Java-kielen perusteet

Sisällys. Metodien kuormittaminen. Luokkametodit ja -attribuutit. Rakentajat. Metodien ja muun luokan sisällön järjestäminen. 6.2

12. Näppäimistöltä lukeminen 12.1

Ohjelmistojen mallintaminen, sekvenssikaaviot

Sisällys. JAVA-OHJELMOINTI Osa 7: Abstrakti luokka ja rajapinta. Abstraktin luokan idea. Abstrakti luokka ja metodi. Esimerkki

Concurrency - Rinnakkaisuus. Group: 9 Joni Laine Juho Vähätalo

Sisältö. 2. Taulukot. Yleistä. Yleistä

Aalto Yliopisto T Informaatioverkostot: Studio 1. Oliot ja luokat Javaohjelmoinnissa

Sisällys. 6. Metodit. Oliot viestivät metodeja kutsuen. Oliot viestivät metodeja kutsuen

Yksikkötestaus. import org.junit.test; public class LaskinTest public void testlaskimenluonti() { Laskin laskin = new Laskin(); } }

OSA I: Yhteisten muuttujien käyttö. Prosessit samassa koneessa. Rio 2004 / Auvo Häkkinen 2-1

OSA I: Yhteisten muuttujien käyttö. Sisältöä. Prosessit samassa koneessa. Poissulkeminen ja synkronointi. Semaforit ja rinnakkaisuuden hallinta

Ohjelmoinnin peruskurssien laaja oppimäärä

7. Näytölle tulostaminen 7.1

2 Konekieli, aliohjelmat, keskeytykset

Opintojakso TT00AA11 Ohjelmoinnin jatko (Java): 3 op Rajapinnat ja sisäluokat

11. Javan valintarakenteet 11.1

Koottu lause; { ja } -merkkien väliin kirjoitetut lauseet muodostavat lohkon, jonka sisällä lauseet suoritetaan peräkkäin.

Ohjelmoinnin perusteet Y Python

Transkriptio:

Helsingin Yliopisto, tietojenkäsittelytieteen laitos Rinnakkaisohjelmointi (syksy 2006) Liite 1. Projektin tulokset (Semaforit Javassa) Jukka Hyvärinen Aleksanteri Aaltonen

a. Käyttötarkoitus ja sovellusalue Semafori on käyttöjärjestelmän tai laitteiston tasolla toteutettu rakenne prosessien synkronointiin. Semaforeja voi käyttää moniin tehtäviin, mutta yksinkertaisimmillaan ne toimivat mutual-exclusion -takeena eli mutexina tarjoten tehokkaan ja yksinkertaisen tavan ohjelmakoodin kriittisen alueen suojaukseen: vain yksi prosessi pääsee suorittamaan tiettyä koodilohkoa kerrallaan. Tämänkaltaista semaforia kutsutaan mutexin lisäksi binäärisemaforiksi, koska sillä voi olla ainoastaan kaksi arvoa: vapaa tai käytössä. Yleisellä semaforilla voi olla suurempiakin arvoja, jotka kuvastavat käytössä olevien resurssien määrää. Nämä resurssit voidaan yleensä jakaa useamman prosessin kesken, siten että varattuna olevien resurssien määrä pysyy aina samana tai pienempänä kuin kaikkien käytössä olevien resurssien määrä, tai yhdistelemällä useita semaforeja oikealla tavalla voidaan kaikki resurssit varata kerrallaan valitulle määrälle (esim. yhdelle) prosesseja. Esimerkkinä tästä on lukijoiden ja kirjoittajien ongelma, jossa lukijoita voi olla aktiivisena kuinka monta tahansa, kunhan kirjoittajia ei ole. Toisaalta yhden kirjoittajan ollessa aktiivisena mitään muuta prosessia ei saa päästä kirjoittamaan tai lukemaan. Yksinkertaisuudestaan huolimatta semaforien avulla on mahdollista toteuttaa melkein mikä tahansa kriittisen alueen ongelma, jossa on käytössä yhteistä muistia, mutta monimutkaisemmissa tapauksissa on järkevämpää käyttää jotain erikoistuneempaa rakennetta. b. Perusidea Semaforin perusidea on yksinkertainen: se tarjoaa atomisen laskurin kasvattamis- tai pienentämisoperaation, sekä toiminnallisuuden prosessien nukuttamiseen tai herättämiseen. Semaforeilla on aina 2 perusoperaatiota: WAIT ja SIGNAL. Prosessin kutsuessa WAIT-käskyä semafori atomisesti laskee laskurin arvoa yhdellä, tai jos laskurin arvo on ei-positiivinen, nukuttaa prosessin asettamalla sen SUSPENDED -tilaan. SIGNAL vastaavasti katsoo, onko semaforilla nukutettuja prosesseja, ja jos on, se herättää niistä yhden asettamalla sen READY TO RUN -tilaan. Muussa tapauksessa se kasvattaa laskurin arvoa yhdellä. Semaforin implementaatio määrää, millä perusteella herätettävä prosessi valitaan. Vahva semafori herättää aina sen prosessin, joka nukutettiin

ensimmäisenä, kun taas heikko semafori herättää satunnaisen semaforissa nukkuvan prosessin. On myös olemassa busy-wait -tyyppisiä semaforeja, jotka eivät muuta prosessin tilaa mitenkään. Sen sijaan ne käyttävät silmukaa, jossa prosessi luuppaa, kunnes laskurin arvo on taas positiivinen. Busy-wait -semafori on kevyempää toteuttaa, mutta toisaalta luuppaava prosessi syö kokoajan laskentatehoa prosessorilta ja sen takia niitä ei kannatakaan käyttää muissa kuin moniprosessorikoneissa, eikä kovin usein niissäkään. Semaforin alkuarvon määrittää sen käyttäjä. Useimmissa implementaatioissa hyväksyttyjä arvoja ovat kaikki ei-negatiiviset kokonaisuluvut (binäärisemaforin tapauksessa 0 ja 1), mutta Javan toteutus hyväksyy epästandardisti myös negatiiviset alkuarvot. Tämä tarkoittaa, että SIGNAL -komentoa täytyy kutsua tietyn monta kertaa, ennenkuin yksikään prosessi voi ohittaa semaforin. Tämä voi olla hyödyllistä esim. tuottaja/kuluttaja - tapauksessa, jossa kuluttaja lukee kerrallaan useita resurssialkioita. Perusoperaatioiden lisäksi monissa toteutuksissa semaforit tukevat suoraan useiden resurssialkioiden varaamista ja vapauttamista kerrallaan, sekä vapaiden alkioiden määrän tarkistamista. c. Yhteneväisyydet / eroavaisuudet kurssilla esitettyyn perustapaukseen Javassa semaforeja varten on selkeästi nimetty luokka, Semaphore. Se löytyy java.util.concurrent paketista. Javan semaforien komentojen terminologia eroaa hieman normaalista, WAIT-käskyä vastaa acquire (tämä johtunee siitä, että Javassa wait on jo varattu monitoreille), kun taas SIGNALia vastaa release. Acquiren seurauksena nukutettu säie voidaan herättää keskeyttämällä säie interrupt -metodilla. Jos tätä ei haluta, voidaan käyttää acquireuninterruptibly-metodia. Javassa voi myös hakea suoraan listan semaforissa odottavista säikeistä, sekä tarkistaa, kuinka paljon resursseja on vapaana. Lisäksi mukana on muutama atominen lisäoperaatio, jotka voisi toteuttaa yllämainittujen yhdistelmänäkin, kuten tryacquire -metodi, joka ei pysäytä prosessia missään vaiheessa, vaan palauttaa false siinä tapauksessa että resursseja ei ole vapaana. tryacquiresta on variantti, joka odottaa määritellyn ajan semaforin vapautumista ennen falsen palauttamista. Vapaiden resurssien määrää voi myös vähentää mielivaltaisesti reducepermits -metodilla. Javan semaforit eivät oletuksena ole vahvoja (Javan oma termi on reiluja ), mutta semaforilla on vaihtoehtoinen konstruktori, jolla tällaisen vahvan semaforin voi luoda.

Muilta osin Javan semaforien toteutus on kohtalaisen standardinomainen. Toisin kuin monitorien tapauksessa, semaforeilla ei ole omistajasäiettä, joten semaforin vapauttavaa release-käskyä voi kutsua mistä tahansa säikeestä. Semaphore-luokan lisäksi javassa useita lukkoluokkia java.util.concurrent.locks -paketissa. Nämä ovat oikeastaan monitoreita, mutta semaforien kannalta kiinnostava on erityisesti ReentrantReadWriteLock, joka ratkaisee yhden perinteisesti semaforeilla toteutetuista rinnakkaisuusongelmista, nimittäien lukijoiden ja kirjoittajien ongelman. Kyseinen lukko mahdollistaa siis useiden lukijoiden tai yhden kirjoittajan kerrallaan aktiivisena olemisen. Käytännössä lukko lukemista varten varataan readlock().lock() -metodilla ja vapautetaan vastaavalla unlock() -metodilla. Kirjoittamista varten lukko varataan writelockin kautta. Lukijoita ja kirjoittajia ei luonnollisesti päästetä suoritukseen samaan aikaan.

d. Esimerkit Aterioivien filosofien ongelma Aterioivien filosofien ongelmassa on 5 filosofia, joilla jokaisella on 2 tehtävää: ensin filosofi ajattelee ja sitten syö, jonka jälkeen hän siirtyy taas ajattelemaan syvällisiä asioita. Filosofeilla on käytössään pyöreä pöytä, jossa on 5 lautasta ja 5 haarukkaa, mutta jokainen filosofi tarvitsee 2 haarukkaa syödäkseen. Ongelmana on jakaa haarukat siten, että jokainen haarukka on enintään yhden filosofin käytössä kerrallaan (kriittisen alueen suojaus) ja ettei kukaan filosofi nälkiinny, eikä tilanne jää jumiin. Ongelman ratkaiseva esimerkkikoodi on tiedostossa s06_philosophers.java PlusMinus-ohjelma laskuharjoitustehtävistä PlusMinus on ohjelma, jossa on yhteisessä muistissa käytettävissä kuusi nollalla alustettavaa muuttujaa: X1, X2, X3, X4, Ctrl ja Sum. PlusMinus-ohjelmassa on viisi laskentaprosessia jotka suorittavat 50 kertaa silmukan, jonka kriittinen vaihe on: - Jos muuttujan Ctrl arvo on pariton, vähennetään kaikista X-muuttujista luku 1. Jos muuttujan Ctrl arvo on parillinen, lisätään kaikkiin X-muuttujiin luku 2. - Lopuksi lisätään muuttujaan Ctrl arvo 1 ja lasketaan kaikkien X-muuttujien summa muuttujaan Sum. Esimerkkikoodissa kriittisen vaiheen suojaus on toteutettu Javan semaforeilla. PlusMinus-ohjelmiston koodi on tiedostossa s06_plusminus.java

e. Käyttöohje Javan semaforien käyttö on helppoa. Käyttö aloitetaan luomalla ensin semafori-olio newkäskyllä. Konstruktorille annetaan resurssien määrä alkutilanteessa sekä haluttaessa optionaalinen tieto siitä, halutaanko semaforin toimivan reilusti vai epäreilusti. Tarvittava Semaphore-luokka on java.util.concurrent-luokan aliluokka. public class MyApp implements Runnable { // Luodaan reilu binäärisemafori ja alustetaan se alkuarvolla 1. private static Semaphore semaphore = new Semaphore(1, true); // Sisältää kriittistä koodia, jota voi päästä suorittamaan vain 1 säie kerrallaan public void importantfunction() { try { // Semafori varataan suorittavalle säikeelle acquire-komennolla, jonka täytyy olla poikkeuksen varalta try-catch -lohkossa. semaphore.acquire(); catch (InterruptedException e) { // Säie keskeytettiin ja tämä keskeytys voitaisiin käsitellä. // Nyt vain yksi säie pääsee suorittamaan tätä koodia doimportantstuff(); // Semafori vapautetaan lopuksi release-komennolla. semaphore.release(); public void run() { // Suoritetaan tärkeä funktio importantfunction(); public static void main(string[] args) { // Luodaan 10 säiettä ja päästetään ne vuorollaan tärkeään funktioon for (int i = 0; i < 10; ++i) { new Thread(MyApp()).start();