*x++=*y++
815338A
Ohjelmointikielten
periaatteet
2014 - 2015
IX Rinnakkainen ohjelmointi
*x++=*y++
Sisältö
1.
2.
3.
4.
5.
6.
7.
Yleistä rinnakkaisuudesta
Prosesseista ja säikeistä
Rinnakkaisen ohjelman oikeellisuudesta
Rinnakkaisuuden kontrollirakenteet
Rinnakkaisuus Javassa
Rinnakkaisuus C++-kielessä
Rinnakkaisuus muissa ohjelmointikielissä
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
2
*x++=*y++
IX.1. Yleistä rinnakkaisuudesta
Peräkkäinen
vs.
Käskyt suoritetaan
peräkkäin
Yksikäsitteinen
suorituspolku
Deterministinen
sama syöte, sama
tulos aina
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
Rinnakkainen
Toimintoja suoritetaan
rinnakkain
Ei selvää suorituspolkua
Epädeterministinen
tulos voi riippua
suoritusjärjestyksestä
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
3
*x++=*y++
IX.1.1. Rinnakkaisuuden tyypit
Parallel programming
Aito (fyysinen) rinnakkaisuus
Vaatii useampia prosessoreja (tai ainakin ytimiä)
Concurrent programming
Rinnakkaisuus voi olla harhaa: suoritetaan yksi
konekielinen käsky kerrallaan
Toiminnot rinnakkain – looginen rinnakkaisuus
Toimii yhdessä prosessorissa
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
4
*x++=*y++
IX.2. Prosesseista ja säikeistä
IX.2.1. Prosessi
Tapa ajaa useita ohjelmia rinnakkain yhdessä
prosessorissa
Oma muistialue
Kommunikointi esim. putkilla
Rinnakkainen suorittaminen aikajaolla
Ominaisuudet riippuvat käyttöjärjestelmästä
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
5
*x++=*y++
IX.2.2. Säikeet
Prosessia kevyempiä
Prosessi voidaan jakaa säikeisiin
Säikeellä oma ohjelmalaskuri ja pino
Säikeet jakavat prosessin muistialueen ja resurssit
Käyttöjärjestelmissä standardi: Pthread (POSIX: IEEE
1003.1)
Tässä monisäieohjelmointia
Liittyy läheisemmin ohjelmointikieliin
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
6
*x++=*y++
IX.2.2.1 Säikeen elinkaari
Uusi
Käynnistys
Ajettava/
Suorituksessa
suoritus
loppuu
odotus
ilmoitus
sleep()
sleep aika
IO esto
IO suoritus
Kuollut
suoritus
loppuu
Estetty
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
7
*x++=*y++
IX.3. Rinnakkaisen ohjelman oikeellisuudesta
Rinnakkaisen ohjelman oikeellisuuskriteerit:
Turvallisuus (safety)
Oliot ja muuttujat pysyvät kunnossa
Eloisuus (liveness)
Kaikki aiotut operaatiot suoritetaan joskus
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
8
*x++=*y++
IX.3.1. 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 millä tahansa
kutsujärjestyksellä
Muuttujan lukeminen ja arvon kirjoittaminen
samanaikaisesti = Luku/Kirjoituskonflikti
Muuttujan arvon kirjoittaminen samanaikaisesti kahdesta
säikeestä= Kirjoitus/Kirjoituskonflikti
Yleistermi kilpailutilanne (race condition)
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
9
*x++=*y++
IX.3.2. Eloisuus
Aiotut operaatiot suoritetaan – ei aikarajaa
Reaaliaikainen ohjelmointi – asetetaan aikarajoja
Turvallisuus ja eloisuus jossain määrin vastakkaisia
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
10
*x++=*y++
IX.3.3. Operaation epäonnistuminen
Operaation suorittamatta jäämisen yleisin syy: odotetaan
resurssin vapautumista, esimerkiksi
Toinen säie on lukinnut suoritettavan metodin
Metodi lukkiutuu odottaen toisen säikeen suorittamaa
tapahtumaa
Pysyvän epäonnitumisen syitä:
Lukkiutuminen (deadlock)
Säikeet ristiinlukitsevat metodit
Nälkiintyminen (starvation)
Säie ei saa lainkaan keskusyksiköltä ajoaikaa
Voi johtua monista syistä
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
11
*x++=*y++
IX.3.4. Synkronointi
Säikeiden jaksottaminen niin, että ohjelman oikeellisuus
varmistuu
Kilpailun synkronointi (competition synchronization)
Tarvitaan, kun kaksi säiettä yrittää toisistaan
riippumatta käyttää jotakin resurssia
Toteutus yleensä: Säie pyytää synkronointioliolta
resurssin käyttöoikeutta, vapauttaa resurssin
lopetettuaan operaationsa
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
12
*x++=*y++
IX.3.4. Synkronointi (2)
Yhteistoiminnan synkronointi (cooperation
synchronization).
Tarvitaan, kun jonkin säikeen A operaation
suorittaminen riippuu toisen säikeen B toiminnasta ->
A joutuu odottamaan, kunnes B saa suoritettua
operaationsa
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
13
*x++=*y++
IX.4. Rinnakkaisuuden kontrollirakenteet
Synkronoinnin hallinnan perusmekanismit Semaforit,
Monitorit, Viestinvälittäminen
Viestinvälittäminen (message passing)
Välttämätön, jollei yhteistä muistialuetta
Adan perusmekanismi
Jaksottaminen hoidetaan lähettämällä ja
vastaanottamalla viestejä
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
14
*x++=*y++
IX.4.1. Semaforit
Vanhimpia rinnakkaisen ohjelmoinnin rakenteita
1968 Dijkstra: THE –käyttöjärjestelmä
E.W. Dijkstra, “The structure of ’THE’
multiprogramming system”, Communications of ACM,
11 (5), 1968, 341 - 346.
Semafori-nimitys rautateiden opastimista
Semafori: Kokonaislukumuuttuja, joka pitää yllä lupien
lukumäärää, arvo ≥ 0
Lupien lukumäärä kuvaa yleensä yhtä aikaa toimivia
säikeitä
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
15
*x++=*y++
IX.4.1. Semaforit (2)
Säie pääsee toimimaan jos saa luvan semaforilta,
muuten odottaa
Kun säie lopettaa toimintansa on ilmoitettava
semaforille
Operaatiot ( S on semafori)
WAIT(S) (tai P(S))
SIGNAL(S) (tai V(S))
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
16
*x++=*y++
IX.4.1. Semaforit (3)
Voidaan käyttää esim.
Poissulkevuuden toteuttamiseen
Laskurina
Periaatteessa kaikki rinnakkaisuuden rakenteet voitaisiin
toteuttaa pelkästään semaforeilla
Monissa tapauksissa kömpelöä
Monissa käyttöjärjestelmissä semafori on ainoa
rinnakkaisuuden kontrollirakenne
UNIX ja Windows tukevat suoraan semaforeja
Melko harvinaisia ohjelmointikielissä
Algol68 ja PL/I
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
17
*x++=*y++
IX.4.2. Monitorit
Semaforit eivät sovi hyvin rakenteiseen ohjelmointiin ->
Tarvittiin uusi rakenne, joka käyttäisi datan kapselointia
C.A.R. Hoare 1974
Esitteli monitorin käsitteen
“Monitors: an operating system structuring
concept”, Communications of ACM, 17 (10) 549-
557, 1974
Concurrent Pascal (Brinch Hansen 1975)
Ensimmäinen ohjelmointikieli, jossa monitorit
käytössä
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
18
*x++=*y++
IX.4.2. Monitorit (2)
Kapseloivat halutut toiminnot sisäänsä
Suoritus mahdollinen vain monitorin suostumuksella
Vain yksi säie kerrallaan: säikeellä hallussaan
monitorin lukko (lock)
Monitorin odotusjoukko (wait set)
Sisältää suoritusta odottavat säikeet
Voi jakaantua osajoukkoihin ehtomuuttujien
(condition variables) suhteen
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
19
*x++=*y++
IX.4.2. Monitorit (3)
Ilmoittaminen (notify, signal)
Lukkoa hallussaan pitävän säikeen luopuminen
lukosta
Odotusjoukosta valitaan jokin säie toimimaan
Mahdollista osoittaa, että monitori voidaan toteuttaa
semaforeilla ja päinvastoin -> monitori ja semafori
ilmaisuvoimaltaan yhtä vahvoja
Monitori kuitenkin käytettävyydeltään korkeammalla
tasolla
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
20
*x++=*y++
IX.5. Rinnakkaisuus Javassa
IX.5.1. Javan säikeet
Käyttäjäsäikeet (user threads)
varsinaiset säikeet
Demonisä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
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
21
*x++=*y++
IX.5.2.Säikeen luominen Javassa
Kirjoita luokka, joka perii Thread-luokan
run-metodi ylikirjoitettava
TAI
Kirjoita luokka joka toteuttaa Runnable-rajapinnan
toteutettava run-metodi
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
22
*x++=*y++
IX.5.2.Säikeen luominen Javassa
Thread-luokan oliot kontrolloivat säikeitä:
1. Luo uusi Thread-olio
2. Konfiguroi
• Anna prioriteetti ja nimi (ei pakollinen)
3. Käynnistä kutsumalla start-metodia
HUOM1: Käynnistys kutsumalla startia, toiminnallisuus
runissa!
HUOM2: Säie päättyy, kun run loppuu.
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
23
*x++=*y++
IX.5.3. Synkronointi Javassa
Javassa monitori sisäänrakennettu rinnakkaisuuden
hallintamekanismi
Jokainen olio voi toimia monitorina -> jokaisella oliolla
on lukko ja odotusjoukko
Javan monitorit ”Ilmoita ja jatka”-tyyppiä
Ilmoituksen saanut säie odottaa, kunnes ilmoittaja poistuu
monitorista ja alkaa tämän jälkeen suorittaa toimintojaan
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
24
*x++=*y++
IX.5.3.1. Esimerkki Javan synkronoinnista: syklinen
puskuri
Käytetään, kun yksi säie tuottaa toiselle säikeelle dataa
ja data on saatava talteen, kunnes se on luettu.
Voidaan toteuttaa taulukkona
Kirjoitus ja lukeminen nopeaa ja yksinkertaista
Pidettävä huoli siitä, että täyteen puskuriin ei enää
kirjoiteta eikä tyhjästä lueta
Viimeisen paikan jälkeen kirjoitetaan aina ensimmäiseen
Luokkaan kirjoitetaan metodit put ja take, joilla
kirjoitetaan puskuriin ja luetaan siitä
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
25
*x++=*y++
IX.5.3.1.1. Kilpailun synkronointi syklisessä
puskurissa
Jos metodeja put ja take kutsutaan kahdesta säikeestä
yhtä aikaa, voi tulla konflikti -> kilpailun synkronoinnilla
estettävä
Onnistuu kirjoittamalla metodit syknronoiduiksi =
lisätään sen esittelyyn sana synchronized -> olio itse
toimii monitorina
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
26
*x++=*y++
IX.5.3.1.1. Kilpailun synkronointi syklisessä
puskurissa (2)
Säie kutsuu synkronoitua metodia -> ottaa haltuunsa
olion lukon
Olion kaikkien synkronoitujen metodien suorittaminen
estyy kunnes säie luopuu lukosta
Lukosta luopuminen:
1.Synkronoitu metodi loppuu tai
2.Säie siirtyy odotustilaan
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
27
*x++=*y++
IX.5.3.1.2. Yhteistoiminnan synkronointi syklisessä
puskurissa
Yo. toteutuksen jälkeen koodissa vielä ongelma: tyhjästä
puskurista luetaan ja täyteen kirjoitetaan.
Oikea toiminta:
Lukeva säie pysähtyy, ellei mitään luettavaa ole.
Jatkaa toimintaansa vasta sitten, kun jokin
kirjoittajasäie käy kirjoittamassa alkion taulukkoon.
Kirjoittava säie pysähtyy, jos puskuri täynnä. Saa
jatkaa toimintaansa vasta, kun jokin lukijasäie käy
lukemassa alkion
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
28
*x++=*y++
IX.5.3.1.2. Yhteistoiminnan synkronointi syklisessä
puskurissa (2)
Käytetään wait/notify-metodeja
wait, notify ja notifyAll ovat Object-luokan metodeja
Koska kaikki oliot perivät Object-luokan, kaikilla
olioilla on myös nämä metodit
wait luopuu lukosta ja jää odottamaan ilmoitusta
notify ja notifyAll annettuna toisesta säikeestä
vapauttavat odottavia säikeitä
Yhdistetään sekä kilpailun että yhteistoiminnan
synkronointi -> Ratkaisu sykliselle puskurille
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
29
*x++=*y++
IX.5.3.1.3. Luokan koodi
public class CircularBuffer{
protected final Object[] buffer;
int putPtr = 0;int takePtr = 0;
int queuedItems = 0;
public CircularBuffer(int size){
buffer = new Object[size];
}
// Put objects to buffer
public synchronized void
put(Object obj) throws
InterruptedException{
// Take objects from buffer
public synchronized Object
take() throws
InterruptedException{
while(queuedItems == 0)
wait();
Object retObj =
buffer[takePtr];
while(queuedItems ==buffer.length)
wait();
takePtr = (takePtr+1)
%buffer.length;
queuedItems--;
buffer[putPtr] = obj;
putPtr = (putPtr+1)%buffer.length;
queuedItems++;
if(queuedItems ==
(buffer.length-1))
notifyAll();
if(queuedItems == 1)
notifyAll();
} // End put()
return retObj;
} // End take()
} // End class CircularBuffer
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
30
*x++=*y++
IX.6. Rinnakkaisuus C++-kielessä
IX.6.1 Säikeet
Standardiin C++11 lisätty rinnakkaisuuden tuki
Säikeiden hallintaan luokka std::thread
Voi suorittaa minkä tahansa funktion koodia omassa
säikeessään
Toinen säie voi odottaa päättymistä (metodi join)
Ohjelma päättyy, kun pääohjelman säie loppuu ->
voidaan tarvita join-kutsua
Voidaan irrottaa taustasäikeeksi (metodi detach)
Ei voida odottaa loppumista
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
31
*x++=*y++
IX.6.1 Säikeet. Esimerkki
#include <iostream>
#include <thread>
void terve(){
std::cout << "Terve. Olen saie "
<< std::this_thread::get_id() << std::endl;
}
int main(){
std::thread saie(terve);
saie.join();
std::cout << "Ohjelman loppu!" << std::endl;
return 0;
}
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
32
*x++=*y++
IX.6.2 Kilpailun synkronointi C++-kielessä
Koodin lukitseminen muilta säikeiltä: Kutsutaan luokan
std::mutex olion lock-metodia
Ei voida suorittaa muista säikeistä ennen unlockkutsua
Esimerkki:
std::mutex lukko;
void kasvata(){
lukko.lock();
++arvo;
lukko.unlock();
}
Lukua arvo voi kasvattaa vain yhdestä säikeestä kerrallaan
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
33
*x++=*y++
IX.6.3 Yhteistoiminnan synkronointi C++-kielessä
C++:ssa ei monitoria vastaavaa luokkaa
Odottaminen ja ilmoittaminen ehtomuuttujilla: luokka
std::condition_variable
Esimerkki
std::mutex lukko; std::condition_variable conOne;
std::condition_variable conTwo;
void kasvata(){
std::unique_lock<std::mutex> lck(lukko);
while(arvo >= max) conOne.wait(lck);
++arvo;
conTwo.notify_one();
}
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
34
*x++=*y++
IX.7. Rinnakkaisuus muissa ohjelmointikielissä
PL/I
IBM, 1960 – luvun puoliväli
Ensimmäinen rinnakkaista ohjelmointia tukeva kieli
Rinnakkaisuuden toteutus oli puutteellinen
Simula (1966 – 67)
Ensimmäinen oliokieli (joidenkin lähteiden mukaan
ensimmäinen rinnakkainen kieli)
Tuki myös rinnakkaisuutta (alkeelliseesti
vuorottelualiohjelmien [coroutines] avulla)
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
35
*x++=*y++
IX.7. Rinnakkaisuus muissa ohjelmointikielissä (2)
Pascal
Ei tue rinnakkaisuutta
1970 –luvun puolivälissä Concurrent Pascal
Sisälsi ensimmäisenä monitorin
C
Ei tue rinnakkaisuutta
Kehitetty Concurrent C
Voidaan toteuttaa rinnakkaisuus käyttöjärjestelmän
ominaisuuksien avulla
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
36
*x++=*y++
IX.7. Rinnakkaisuus muissa ohjelmointikielissä (3)
Ada
1983 Yhdysvaltain puolustusministeriön
kehitysprojekti
Tukee rinnakkaista ohjelmointia (Adan säie = task)
Synkronointi perustuu viestinvälitykseen
1995 parannettu versio
C#
Rinnakkaisuus samankaltainen kuin Javassa
Muutokset Sebestan mukaan merkittäviä ja
parantavat Javan säietoteutusta
Ari Vesanen, Tietojenkäsitttelytieteiden laitos
815338A Ohjelmointikielten periaatteet, Rinnakkainen ohjelmointi
37
© Copyright 2025