Sočasno programiranje z uporabo niti v Javi

41
Zoran Bosnić Ljubljana, februar 2010

Transcript of Sočasno programiranje z uporabo niti v Javi

Page 1: Sočasno programiranje z uporabo niti v Javi

Zoran Bosnić

Ljubljana, februar 2010

Page 2: Sočasno programiranje z uporabo niti v Javi

Kazalo 1.) UVOD: sočasnost, procesi in niti

2.) JAVA: izdelava in uporaba niti v Javi

3.) SINHRONIZACIJA:

sinhronizirane metode

sinhronizirani bloki

sinhronizacija s komunikacijo

4.) PROBLEMI: problemi pri zasnovi sočasnih programov

Page 3: Sočasno programiranje z uporabo niti v Javi

Sočasnost

večopravilnost (angl. multitasking): sposobnost istočasnega izvajanja več opravil

=> pravimo, da se opravila izvajajo sočasno (concurrent)

sočasnost:

sočasno izvajanje različnih programov(npr. več programov znotraj operacijskega sistema)

sočasno izvajanje opravil znotraj programa (npr. več nalog, ki jih mora izvesti določen program)

primeri v praksi?

Page 4: Sočasno programiranje z uporabo niti v Javi

Primer!

Page 5: Sočasno programiranje z uporabo niti v Javi

Proces in nit

PROCES NIT

zaključena programska celotasestavni del procesa, vsak ima vsaj eno nit

ima svoje vire (rezerviran pomnilnik)

niti si delijo vire nadrejenega procesa

omogoča sočasno izvajanje različnih programov

omogočajo sočasnost znotraj programa

zahtevna, a neobveznamedprocesna komunikacija

preprostejša, a skoraj obveznakomunikacija med nitmi

Page 6: Sočasno programiranje z uporabo niti v Javi

PROCESI NITI

PROGRAMI hellow, foobar in test PROGRAM foobar

Proces in nit

komunikacija(opcijsko)

Page 7: Sočasno programiranje z uporabo niti v Javi

1.) UVOD: sočasnost, procesi in niti

2.) JAVA: izdelava in uporaba niti v Javi

3.) SINHRONIZACIJA:

sinhronizirane metode

sinhronizirani bloki

sinhronizacija s komunikacijo

4.) PROBLEMI: problemi pri zasnovi sočasnih programov

Page 8: Sočasno programiranje z uporabo niti v Javi

Kako naredimo nit?

1. pristop: dedovanje iz razreda Thread ustvarimo nov razred (npr. NitDedovana), ki deduje iz Thread,

izdelamo primerek razredaNitDedovana mojaNit = new NitDedovana();

poženemo nitmojaNit.start();

2. pristop: implementacija vmesnika Runnable ustvarimo nov razred (npr. NitRunnable), ki implementira vmesnik Runnable,

izdelamo primerek razreda ThreadThread mojaNit = new Thread(new NitRunnable());

poženemo nitmojaNit.start();

Page 9: Sočasno programiranje z uporabo niti v Javi

Izdelava niti

1. pristop: dedovanje iz razreda Thread

public class NitDedovana extends Thread {

public void run() {

// koda niti

}

public static void main() {

NitDedovana mojaNit = new NitDedovana();

mojaNit.start();

}

}

Page 10: Sočasno programiranje z uporabo niti v Javi

Izdelava niti

2. pristop: implementacija vmesnika Runnable

public class NitRunnable implements Runnable {

public void run() {

// koda niti

}

public static void main() {

Thread mojaNit = new Thread(new NitRunnable());

mojaNit.start();

}

}

Page 11: Sočasno programiranje z uporabo niti v Javi

Kdaj uporabiti kateri pristop?

1. pristop: dedovanje iz razreda Thread + preprosteje

- dedujemo lahko samo od enega razreda naenkrat...

2. pristop: implementacija vmesnika Runnable - bolj zahtevna sintaksa

+ bolj splošno

Page 12: Sočasno programiranje z uporabo niti v Javi

Kako upravljati z nitmi?

Thread.start() požene ustvarjeno nit iz začne z izvajanjem njene metode run()

Thread.sleep()

Thread.sleep(cas)ustavi izvajanje niti za določen čas

Thread.interrupt()zahteva od niti prekinitev delovanja(sproži izjemo InterruptedException, če je nit na čakanju)

Object.wait()

Object.wait(cas)

Object.notifyAll()

Object.notify()

metodi za sinhronizacijo niti; wait() ustavi izvajanje niti, notifyAll() / notify() sporoči niti, da lahko nadaljuje z delom

Thread.setName(),

Thread.getName()

nastavi in vrne ime niti; ime lahko nastavimo tudi z uporabo konstruktorja new Thread(string)

Thread.setPriority(),

Thread.getPriority()

nastavi niti prioriteto izvajanje med 1 (=Thread.MIN_PRIORITY) in 10 (=Thread.MAX_PRIORITY). Privzeta vrednost je 5 (=Thread.NORM_PRIORITY).

Page 13: Sočasno programiranje z uporabo niti v Javi

Življenjski cikel niti

Page 14: Sočasno programiranje z uporabo niti v Javi

Adam

Branko

Milan

Primer uporabe niti

igra iskanja razlik na sliki

--- <<<zacetek igre>>> ---

Branko je nasel razliko 1

Milan je nasel razliko 1

Adam je nasel razliko 1

Milan je nasel razliko 2

Milan je nasel razliko 3

Branko je nasel razliko 2

Adam je nasel razliko 2

Branko je nasel razliko 3

Adam je nasel razliko 3

Branko je nasel razliko 4

Milan je nasel razliko 4

Adam je nasel razliko 4

Adam je nasel razliko 5

KONEC STETJA! Adam je nasel vseh 5 razlik in je zmagovalec!

--- <<<konec igre>>> ---

Page 15: Sočasno programiranje z uporabo niti v Javi

Primer

private int prvi;

private int drugi;

public int sestej();}

public void nastaviPrvi(int x);

public void nastaviDrugi(int x);

razred SeštevkoBlagajna 1

Blagajna 2

Blagajna 3

Blagajna 4

prvi

drugi

prvi+drugi

razred Sestevko - omogoča izračun vsote

razred Blagajna - predstavlja našo nit

razred Program - vsebuje metodo main, iz katere ustvarimo 4 niti in jih poženemo

Program

Page 16: Sočasno programiranje z uporabo niti v Javi

Primer razred Sestevko

public class Stoparica {

private int prvi; // vrednost prvega sestevanca

private int drugi; // vrednost drugega sestevanca

Sestevko();

public int sestej();

public void nastaviPrvi(int x);

public void nastaviDrugi(int x);

}

razred Blagajna(=nit)

public class Blagajna extends Thread {

Blagajna(String ime, Sestevko st);

private Sestevko sestevko1; // primerek razreda Sestevko

public void run();

}

razred Program (=glavni program)

Page 17: Sočasno programiranje z uporabo niti v Javi

In program deluje takole...

Nit 1 prosi Sestevka za 4+9

Nit 4 prosi Sestevka za 2+4

Nit 3 prosi Sestevka za 9+8

Sestevko: sporocilo za Nit 4: vsota 9 in 8 je enaka 17

Sestevko: sporocilo za Nit 2: vsota 9 in 8 je enaka 17

Nit 2 prosi Sestevka za 0+2

Nit 4 prosi Sestevka za 6+9

Sestevko: sporocilo za Nit 1: vsota 6 in 9 je enaka 17

Sestevko: sporocilo za Nit 4: vsota 6 in 9 je enaka 15

...

Page 18: Sočasno programiranje z uporabo niti v Javi

Problemi...

private int prvi;

private int drugi;

public int sestej();}

public void nastaviPrvi(int x);

public void nastaviDrugi(int x);

razred SeštevkoBlagajna 1

vsota 6 in 1 je enaka ...

Blagajna 2

Blagajna 3

Blagajna 4

6

3

Problem 1 (znotraj Sestevka): Medtem, ko Sestevko izvaja izračun in izpise sporočilo, mu druga nit spremeni vrednost števil

vsota 6 in 1 je enaka 4!

1

6

1

3

Page 19: Sočasno programiranje z uporabo niti v Javi

Problemi...

private int prvi;

private int drugi;

public int sestej();}

public void nastaviPrvi(int x);

public void nastaviDrugi(int x);

razred SeštevkoBlagajna 1

Blagajna 2

Blagajna 3

Blagajna 4

A1

B1

SESTEJB1 + B2 !!!

Problem 2 (Blagajne niso usklajene): Druga blagajna spremeni vrednost števil še preden prva zahteva seštevek

A2

B2

A1

A2

B1

B2

Page 20: Sočasno programiranje z uporabo niti v Javi

Zakaj pride to težav?

Metode so asinhrone:(vrstni red izvajanja stavkov v nitih je nedorečen):

prepletanje operacij nad skupnimi spremenljivkami

hranjenje lokalnih kopij globalnih spremenljivk

Rešitev:

sinhronizacija metod

Page 21: Sočasno programiranje z uporabo niti v Javi

1.) UVOD: sočasnost, procesi in niti

2.) JAVA: izdelava in uporaba niti v Javi

3.) SINHRONIZACIJA:

sinhronizirane metode

sinhronizirani bloki

sinhronizacija s komunikacijo

4.) PROBLEMI: problemi pri zasnovi sočasnih programov

Page 22: Sočasno programiranje z uporabo niti v Javi

Sinhronizacija

Trije mehanizmi za sinhronizacijo niti:

z zaklepanjem objektov1. sinhronizirane metode (synchronized methods)

2. sinhronizirani stavki (synchronized statements)

z med-nitno komunikacijo3. uporaba mehanizmov čakanja in obveščanja

(wait() in notify())

Page 23: Sočasno programiranje z uporabo niti v Javi

vsak objekt ima notranjo zaporo (intrinsic lock)

public synchronized void metoda() {...}

če nit izvaja sinhronizirano metodo, s tem vzpostavi notranjo zaporo objekta (druge niti do objekta preko sinhroniziranih metod ne morejo dostopati),

ko nit zaključi z izvajanjem sinhronizirane metode, se notranja zapora sprosti (objekt je ponovno na razpolago vsem nitim),

medtem ko Nit1 izvaja dostop do objekta preko sinhronizirane metode, lahko Nit2 do objekta še vedno dostopa preko nesinhroniziranih metod

(1) Sinhronizirane metode

Nit 1

Nit2

sinhroniziranaMETODA 2

sinhroniziranaMETODA 1

nesinhronizirana metoda

Page 24: Sočasno programiranje z uporabo niti v Javi

Sinhronizacija metod razreda

private int prvi;

private int drugi;

public synchronized int sestej();

public synchronized void nastaviPrvi(int x);

public synchronized void nastaviDrugi(int x);

razred SeštevkoBlagajna 1

vsota 6 in 1 je enaka ...

Blagajna 2

Blagajna 3

Blagajna 4

6

3

vsota 6 in 1 je enaka 7!

1

6

1

Page 25: Sočasno programiranje z uporabo niti v Javi

Sinhronizirane metode

Primer

sinhronizacija metod razreda

Page 26: Sočasno programiranje z uporabo niti v Javi

In program deluje sedaj takole...

Nit 3 prosi Sestevka za 9+7

Nit 2 prosi Sestevka za 4+2

Nit 4 prosi Sestevka za 1+7

Nit 1 prosi Sestevka za 5+5

SestevkoSyn: sporocilo za Nit 3: vsota 1 in 7 je enaka 8

Nit 3 prosi Sestevka za 8+2

SestevkoSyn: sporocilo za Nit 2: vsota 8 in 2 je enaka 10

SestevkoSyn: sporocilo za Nit 3: vsota 8 in 2 je enaka 10

Nit 3 prosi Sestevka za 6+8

Nit 2 prosi Sestevka za 5+0

SestevkoSyn: sporocilo za Nit 4: vsota 8 in 2 je enaka 10

Nit 4 prosi Sestevka za 8+4

SestevkoSyn: sporocilo za Nit 1: vsota 6 in 8 je enaka 14

...

seštevki so sedaj pravilni

še vedno ni pravilen vrstni red odgovorov in vrnjene vrednosti nitim

Page 27: Sočasno programiranje z uporabo niti v Javi

(2) Sinhronizirani stavki• kritične dele kode (bloke) v metodi označimo kot sinhronizirane;

kot argument sinhroniziranega bloka navedemo objekt, ki se uporabi za zaklepanje

synchronized(Objekt)

{

// programska koda

}

• bolj podrobno od nivoja procedure; možnost navedbe objekta

nit 1

Nit 1

zakleni Sestevcek samo zame!

delaj a, b, c, d...

sprosti Sestevcek

Nit2

Page 28: Sočasno programiranje z uporabo niti v Javi

(2) Sinhronizirani stavki

Primer

synchronized(sestevko1) {

System.out.println(getName() + " prosi Sestevka za " + a + "+" + b);

sestevko1.nastaviPrvi(a);

sestevko1.nastaviDrugi(b);

pocniNekaj();

sestevko1.sestej(getName());

}

sestevko1 je zaklenjen za nit med celim zaporedjem opravil!

Page 29: Sočasno programiranje z uporabo niti v Javi

Problemi...

private int prvi;

private int drugi;

public int sestej();}

public void nastaviPrvi(int x);

public void nastaviDrugi(int x);

razred SeštevkoBlagajna 1

Blagajna 2

Blagajna 3

Blagajna 4

A1

B1

SESTEJA1 + A2

A2

B2

Page 30: Sočasno programiranje z uporabo niti v Javi

In program sedaj deluje

Nit 2 prosi Sestevka za 9+2

SestevkoSynB: sporocilo za Nit 2: vsota 9 in 2 je enaka 11

Nit 1 prosi Sestevka za 2+9

SestevkoSynB: sporocilo za Nit 1: vsota 2 in 9 je enaka 11

Nit 3 prosi Sestevka za 1+2

SestevkoSynB: sporocilo za Nit 3: vsota 1 in 2 je enaka 3

Nit 4 prosi Sestevka za 5+2

SestevkoSynB: sporocilo za Nit 4: vsota 5 in 2 je enaka 7

Nit 3 prosi Sestevka za 9+8

SestevkoSynB: sporocilo za Nit 3: vsota 9 in 8 je enaka 17

Nit 1 prosi Sestevka za 5+8

SestevkoSynB: sporocilo za Nit 1: vsota 5 in 8 je enaka 13

...

Page 31: Sočasno programiranje z uporabo niti v Javi

(3) Sinhronizacija s komunikacijo ideja: ena nit čaka, da je izpolnjen pogoj, takrat jo obudimo

SLABO: čakanje v prazni zanki

public void run() {

while(!pogoj) {

//cakaj, dokler ni izpoljen pogoj

}

// NADALJUJ Z IZVAJANJEM PROGRAMA...

}

BOLJŠA REŠITEV: uporaba wait() in notifyAll()

public synchronized void procedura() {

while(!pogoj) {

try {

wait();

} catch (InterruptedException e) { }

}

// NADALJUJ Z IZVAJANJEM PROGRAMA...

}

potrošno glede procesorskega časa

• čakamo (stanje WAITING), dokler nas ne obudi notifyAll()

• preverimo, ali smo dočakali pravi pogoj za nadaljevanje

Page 32: Sočasno programiranje z uporabo niti v Javi

(3) Sinhronizacija s komunikacijo

Primer: proizvajalec in potrošnik oba procesa si delita skupni podatek (spremenljivka Podatek),

potrošnik bere podatke, ki jih generira proizvajalec

Proizvajalec:

generira nov podatek in ga shrani v spremenljivko Podatek

ne sme generirati novega podatka, preden potrošnik bere prejšnjega

Potrošnik:

bere podatek iz spremenljivke Podatek in ga obdela

ne sme brati podatka, preden ga je proizvajalec generiral

Page 33: Sočasno programiranje z uporabo niti v Javi

(3) Sinhronizacija s komunikacijo

Primeri:

proizvajalec in potrošnik v Javi (program Loterija)

proizvajalec in potrošnik: primeri iz prakse?

Page 34: Sočasno programiranje z uporabo niti v Javi

Kdaj uporabiti sinhronizirane metode, stavke in sinhronizacijo s komunikacijo?

sinhronizirane metode: v kritičnem razredu, kadar želimo onemogočiti izvajanje več sihnroniziranih metod naenkrat,

sinhronizirane stavke: v niti, ki potrebuje zaklepanje objekta v daljšem zaporedju stavkov,

komunikacija z wait() in notifyAll(): kadar imamo veliko niti, ki lahko počnejo različne stvari.

Pozor! Sinhronizirano kodo uporabljajmo premišljeno! (potrebno je ovijanje objekta v monitor)

T(navadna metoda) < T(sinhr. metoda) < T (sinhr. blok)

Torej...

10 - 100x !

Page 35: Sočasno programiranje z uporabo niti v Javi

1.) UVOD: sočasnost, procesi in niti

2.) JAVA: izdelava in uporaba niti v Javi

3.) SINHRONIZACIJA:

sinhronizirane metode

sinhronizirani bloki

sinhronizacija s komunikacijo

4.) PROBLEMI: problemi pri zasnovi sočasnih programov

Page 36: Sočasno programiranje z uporabo niti v Javi

Težave pri sočasnem izvajanju

1. Mrtva točka (deadlock)niti neskončno dolgo čakajo ena na drugo, zaradi česar se izvajanje programa ne more nadaljevati

2. Živi objem (livelock)niti se začnejo intenzivno odzivati na medsebojne operacije, tako da program ne more globalno napredovati

3. Stradanje (starvation)nit ne more pridobiti dovolj resursov za nadaljevanje svojega dela

Page 37: Sočasno programiranje z uporabo niti v Javi

1. Mrtva točka (deadlock)

primer (1): krožno čakanje na vire

public static Object miza = new Object();

public static Object stol = new Object();

public void prva() {

synchronized (miza) {

synchronized (stol) {

// ... koda niti ...

} } }

public void druga() {

synchronized (stol) {

synchronized (miza) {

// ... koda niti

} } }

prva

druga

hočem stol

hočem mizo

Page 38: Sočasno programiranje z uporabo niti v Javi

primer (2): filozofi pri kosilu (dining philosophers problem)

razmišlja lačen jé

1. Mrtva točka (deadlock)

Page 39: Sočasno programiranje z uporabo niti v Javi

2. Živi objem3. Stradanje

2. Živi objem (livelock)

primer: niti – pešca, ki se izmikata eden drugemu

3. Stradanje

primeri:

nit nima zadostne prioritete,

nit neskončno čaka na zaklenjen objekt,

uporaba notify (namesto notifyAll): vedno obudi druge niti

Page 40: Sočasno programiranje z uporabo niti v Javi

Kako rešujemo te probleme?

1. Skrbno načrtovanje dostopov do posameznih virov v programu (zaporedje zaklepanj)

2. Implementacije "pametne" logike, ki zna reševati težave pri sočasnem dostopu (naključni dogodki, ki prekinejo cikel)

Page 41: Sočasno programiranje z uporabo niti v Javi

Povzetek definicije pojmov: sočasnost, procesi in niti

izdelava in uporaba niti v Javi

sinhronizacija niti: sinhronizirane metode, stavki, komunikacija

problemi pri sočasnem izvajanju: mrtva točka, živi objem, stradanje