Objektorienterad Realtidsprogrammering
2000
Java: kort introduktion.
Trådar.
Något om mutex, Dekkers algoritm och
monitorer.
Javas ("inbyggda monitor") synchronized.
previous
next
Java och trådning
Java
• Java är konstruerat på SUN
– Första versionen släpptes 1995
• Starkt typat
– Dvs det går att avgöra typkompatibilitet av alla uttryck i programmet vid
kompileringstillfället.
• Virtuell maskin (VM) som gör det maskinoberoende
– En speciell VM per plattformstyp överbryggar olikheter i plattformarnas arkitektur
• Klassbibliotek
– språkklasser, stränghantering, grafik, gränssnitt, fönster, Internet,
händelsehantering, processer, collections, mm
• Bindning till WWW
– med applets och liknande
• Har fått sin huvudsakliga spridning via Internet
• Syntax som C. Semantik och klasser mer som Smalltalk
previous
next
2
Java och trådning
Arkitektur
källkod
kompilera
(javac)
java bytekod
kör
(java)
en virtuell
maskin
per plattformstyp
previous
next
Pc
VM
Mac
VM
Unix
VM
3
Java och trådning
Java: mitt första "program"
• Skapa en fil med namnet MyFirstProgram.java
• Skriv följande kod i filen:
import java.io.*;
public class MyFirstProgram{
public static void main (String [] args){
System.out.println("Mitt första program!");
}
}
previous
next
4
Java och trådning
... kompilera och kör
• Kompilera
>javac MyFirstProgram.java
• Då genereras en körbar fil MyFirstProgram.class
• Kör genom att starta Javas virtuella maskin med
program/klassnamnet som argument
>java MyFirstProgram
Mitt första program!
• Regeln är att klassens static void main-metod alltid
exekveras
previous
next
5
Java och trådning
Ett "Javaprograms" struktur
• En klass ser ut på följande sätt
public class KlassNamn extends
SuperKlassNamn{
attribut (instans- och klassvariabler)
Kallas också
för
metoder (instans- och klassmetoder)
medlemmar
konstruktörer
}
• En metod
modifierare returtyp funktionsnamn(argument){
programsatser
}
previous
next
6
Java och trådning
Konstruera klass
• Klassnamn = filnamn
– En klass skall ha samma namn som den fil den placeras i
• Klassen Circle i filen Circle.java
• En fil kan innehålla flera klasser men bara en av dem kan
vara deklarerad public,
– Det är den publika klassens namn som motsvarar filens
• Definition av klass, mall
instansvariabler
metoder
konstruktörer
previous
public class KlassNamn extends SuperKlassNamn{
Modifierare TypIvar1 ivar1;
Modifierare MetodTyp metod1(TypArg1 arg1) {}
public KlassNamn() {}
}
next
7
Java och trådning
Deklarera och instansiera
• Deklaration av instans
KlassNamn variabelNamn;
• Instansiering
variabelNamn = new KlassNamn();
alternativt, både deklaration och instansiering på en
gång
KlassNamn variabelNamn = new KlassNamn();
previous
next
8
Java och trådning
Kompilera och köra
• Environmentvariabel
– För bekväm hantering sätt path (se systemdokumentation) så
att kompilator, virtuell maskin och bibliotek enkelt hittas
• Plattformsberoende hur detta går till
• Kompilera med javac filnamn
javac KlassNamn.java
– om allt går bra skapas då en fil med namnet
KlassNamn.class
• Kör med java klassnamn
java KlassNamn
previous
next
9
Java och trådning
Typer
• I Java måste alla variabler och metoder deklareras med typ
Typ variabel;
• Det finns primitiva typer som int, char, float och boolean
int x;
• En variabel kan ges ett initialt värde vid deklarationen
int x = 10;
• Man kan också använda typer som är implementerade som
vanliga klasser
String course = "O2R";
previous
next
10
Java och trådning
Modifierare
• En modifierare kan användas för att ange vilka objekt som kan
accessa en klass eller dess medlemmar (dvs dess attribut eller
metoder), mest grundläggande är:
static
• indikerar att medlemmen är klassvariabel eller klassmetod
public
• medlemmen är accessbar överallt där dess klass är accessbar
protected
• medlemmen endast accessbar i klassen, dess subklasser eller i aktuellt
package (vi återkommer till package vid senare tillfälle)
private
• medlemmen endast accessbar i den klass som definierar den
ingen modifierare
• accessbar av andra klasser i samma paket
previous
next
11
Java och trådning
Exempel
public class BankAccount{
protected int balance = 0;
public void deposit (int amount) {
balance = balance + amount;
}
public void withdraw (int amount) {
balance = balance - amount;
}
public int balance (){
return balance;
}
}
previous
next
12
Java och trådning
...
BankAccount account1, account2;
int transfer;
account1 = new BankAccount();
account2 = new BankAccount();
account1.deposit(200);
account2.deposit(100);
transfer = 75;
account1.withdraw(transfer);
account2.deposit(transfer);
account2.balance(); // resultat 175
previous
next
13
Java och trådning
Klasser
• En klass och dess metoder skrivs i en enda fil med
samma namn som klassen
• En fil kan innehålla både klass som används av andra
klasser och hjälpklasser, s.k. inre klasser
• En klass kan vara public, dvs åtkomlig för alla,
protected, dvs endast åtkomlig för klasser i samma paket
eller subklasser, paketåtkomstbar, dvs endast åtkomlig
av andra klasser i samma paket eller slutligen private,
dvs bara åtkomlig av klasser i dess omedelbara
omgivning (~fil)
previous
next
14
Java och trådning
Interface
• Ett interface beskriver API-et för en viss grupp av klasser (som
deklarerar att dom implementerar detta gränssnitt)
• Ett interface
– placeras, precis som en klass, i en fil med samma namn som interfacet med
suffixet .java
– kompileras med javac för att generera en .class-fil
• Ett interface deklarerar endast metodapier (och eventuellt
konstanter)
• Motsvarar en pure abstract class i C++
previous
next
15
Java och trådning
Trådar
• En tråd, lättviktsprocess eller exekveringsomgivning är en viss
sekvens av kontroll inom ett program
Program med två trådar
• I Java skapas en tråd som antingen subklass till klassen Thread
eller genom att implementera gränssnittet Runnable i båda
fallen skrivs en metod run som definierar vad som skall göras i
tråden
previous
next
16
Java och trådning
Subklassa Thread eller implementera Runnable
• Beskriva egen tråd genom att subklassa Thread
class MyThread extends Thread {
public void run() {
//Här beskriver vi vad som skall göras så länge tråden
"lever"
//ofta en while-loop med stoppvillkor
}
}
«interface»
relevanta
delar av
Thread
samt
Runnable
Thread
Runnable
run(): void
run(): void
MyThread
run(): void
previous
next
17
Exempel
Alternativ notation
för att visa att Thread
implementerar Runnable
Java och trådning
Runnable
Thread
public class MyThread extends Thread {
public void run() {
int x = 0;
MyThread
while(x < 100) {
System.out.println("x: " + x);
x++;
}
}
}
• Vi testar tråden, dvs startar via meddelandet start
MyThread myThread = new MyThread();
myThread.start();
previous
next
18
Java och trådning
... trådar med Runnable
• I många fall fungerar det inte att
subklassa Thread utan vi vill
kanske ha en annan superklass
«interface»
Runnable
run()
MyRunnable
run()
• Då kan vi istället implementera Runnable
public class MyRunnable implements Runnable {
public void run() {
int x = 0;
while(x < 100) {
System.out.println("x: " + x);
x++;
}
}
}
previous
next
19
Java och trådning
...
• och testar genom att starta en instans av vår klass via
klassen Thread
Thread
relevanta
delar av
Thread
target : Runnable
run(): void
if (target != null) {
target.run();
}
Thread(Runnable r)
target = r;
Thread wrappingThread = new Thread(new MyRunnable());
wrappingThread.start();
• Vi ser på fler exempel från Suns tutorial om trådar
previous
next
20
Java och trådning
Uppdatering av gemensam resurs
Antag att vi har följande program (beskrivet med ett aktivitetsdiagram)
Ge värden för a, b, c och d
m1 = max(a, b);
m2 = max(c, d);
m = max(m1, m2);
Här har det ingen betydelse om m1 eller m2 beräknas
först då satserna disjunkta
previous
next
21
Java och trådning
... med tidsberoende beteende
Om vi istället betraktar följande program
j = 10;
j.print();
j = 100;
Så är resultatet (utskriften via print) beroende av vilken
av grenarna som utförs först
previous
next
22
Java och trådning
Bankkonto med flera trådar kan ge problem
BankAccount
b1 = balance;
balance = b1 + amount;
int balance = 0
deposit(int amount)
withdraw(int amount)
b2 = balance;
balance = b2 - amount;
vi initierar kontot (sätter in 500)
account.balance = 500
previous
Tråd 1
Tråd 2
//visa kontohavare1 balansen
//visa kontohavare2 balansen
account.balance.display()
account.balance.display()
//kontohavare1 tar ut belopp
//kontohavare2 sätter in belopp
account.withdraw(100)
account.deposit(200)
// visa hur mycket som finns på kontot
// visa hur mycket som finns på kontot
account.balance.display()
account.balance.display()
next
23
Java och trådning
Bankkonto och flera trådar, problem
• Om flera trådar samtidigt har möjlighet att uppdatera bankkontot
så får vi tidsberoende resultat
• Beroende av ordning kommer kontot nu ha 400, 600 eller 700
Tråd1
Möjlighet 1
Tråd2
b1 = balance
b1
b2
500
b2 = balance
balance = b2 + 200
500
500
700
balance = b1 - 100
Tråd1
Möjlighet 2-3
400
Tråd2
b1 = balance
balance = b1 - 100
(samma resultat
om tråd 2 först)
Tråd1
Tråd2
b1 = balance
balance = b2 + 200
balance
500
400
400
600
b1
b2
500
balance = b1 - 100
next
b2
500
b2 = balance
previous
b1
b2 = balance
balance = b2 + 200
Möjlighet 4
balance
balance
500
500
400
700
24
Java och trådning
Kritiska regioner
• I bankkontoexemplet kan vi identifiera kritiska regioner som
måste exekveras tillsammans
• Både kodkroppen i withdraw och deposit är kritiska
regioner
Kritisk
region
b1 = balance;
balance = b1 + amount;
b2 = balance;
balance = b2 - amount;
• vi vill skydda kritisk region
– en process i taget i regionen
– ingen annan process ska få komma in om någon annan redan där
– helst skall ingen process behöva vänta i det oändliga på att komma in
previous
next
25
Java och trådning
Mutex
• Kritiska regioner kan skyddas med olika tekniker för inbördes
exklusiv exekvering (mutexbegin/mutexend)
• Man använder lås innan man exekverar kritisk region och släpper
det när man är klar med kodavsnittet
mutexbegin;
b1 = balance;
balance = b1 + amount;
mutexend;
• Man kan skydda med
– semafor
– monitor
– brevlåda
• Vi kommer titta närmare på monitorer, semaforer och relaterade tekniker
previous
next
26
Java och trådning
Dekkers algoritm
• En implementation av mutexbegin/mutexend av den
Holländska matematikern Dekker
mutexbegin:
need(me) = true;
while(need(other)) {
if(turn != me) {
need(me) = false;
while(turn != me);
need(me) = true;
}
}
mutexend:
need(me) = false;
turn = other;
previous
next
27
Java och trådning
...
• Korrekt
• Men
– hopplös komplicerad om vi har fler än två processer
– använder busy-wait vilket vi också vill undvika
previous
next
28
Java och trådning
Monitorer
• En monitor är ett objekt som kan fungera som ett staket
runt kritisk data
• En monitor används för att låsa en viss kritisk region.
Medan kodsekvens/objekt finns i monitorn kan ingen
annan exekvera denna region/del av objektet
previous
next
29
Java och trådning
Exklusiv exekvering av delar av objekt
• I Java finns en inbyggd konstruktion för att hantera
kritiska regioner
– Om man använder nyckelordet synchronized antingen i
en metoddeklaration
synchronized void metod()
{
//...
}
– eller genom att låsa ett objekt i ett visst kodblock
//...
synchronized(lockObject)
{
//...
}
previous
next
30
Java och trådning
...
• Det förstnämnda fallet är ekvivalent med att skriva
void metod()
{synchronized(this)
{
//...
}
}
• Vad som händer är att alla synkroniserada kodavsnitt placeras i en
monitor för objektet i vilket bara en tråd i taget kan befinna sig
– Dvs alla synchronized-deklarerade metoder och kodavsnitt låses
– Andra metoder och kodavsnitt är inte låsta
previous
next
31
Java och trådning
Bankkonto med flera trådar: lös problemet med synchronized
En enkel lösning på problemet är att använda
synchronized i dom kritiska regionerna
BankAccount
int balance = 0
deposit(int amount)
withdraw(int amount)
synchronized(this) {
b1 = balance;
balance = b1 + amount;
}
synchronized(this) {
b2 = balance;
balance = b2 - amount;
}
Nu kommer dom kritiska regionerna köras odelade
och endast en av regionerna kan köras i taget
previous
next
32
Java och trådning
...bankkonto
• Enklast är att deklarera metoderna som synkroniserade
public class SynchronizedBankAccount1{
protected int balance = 0;
public synchronized void deposit (int amount) {
balance = balance + amount;
}
public synchronized void withdraw (int amount) {
balance = balance - amount;
}
public int balance (){
return balance;
}
}
previous
next
33
Java och trådning
...bankkonto alternativ med subklass
• Alternativt skulle vi kunna subklassa och skriva över
dom metoder som behöver synkroniseras
public class SynchronizedBankAccount2 extends BankAccount{
public synchronized void deposit (int amount) {
super.deposit(amount);
}
public synchronized void withdraw (int amount) {
super.withdraw(amount);
}
}
Metoder som inte är synkroniserade
i superklasser kan skrivas över
i subklass och samtidigt deklareras
som synkroniserade
previous
next
34