Διδάσκων: Παναγιώτης Ανδρέου



Σχετικά έγγραφα
Ορισµός Νήµα (thread) είναι µια ακολουθιακή ροή ελέγχου (δηλ. κάτι που έχει αρχή, ακολουθία εντολών και τέλος) σ ένα

Διάλεξη Εισαγωγή στη Java, Μέρος Γ

Προγραμματισμός ΙΙ (Java) 10. Πολυνηματικές εφαρμογές

Οντοκεντρικός Προγραμματισμός

Το παρακάτω πρόγραμμα ορίζει δυο κλάσεις την SimpleThread και την TwoThreadsTest:

Τ.Ε.Ι. Μεσολογγίου, Τµήµα τηλεπικοινωνιακών Συστημάτων & Δικτύων

Εισαγωγή στην Java. Module 9: Threads. Prepared by Chris Panayiotou for EPL /03/2004

Νήµαταστην Java. Συγχρονισµός νηµάτων Επικοινωνία νηµάτων Εκτελέσιµα αντικείµενα Νήµατα δαίµονες Οµάδες νηµάτων. Κατανεµηµένα Συστήµατα 11-1

Αντικειμενοστρεφής Προγραμματισμός

Καρακασίδης Αλέξανδρος Καστίδου Γεωργία Παπαφώτη Μαρία Πέτσιος Κων/νος Στέφανος Σαλτέας Καλογεράς Παναγιώτης. Threads in Java ΝΗΜΑΤΑ ΣΤΗ JAVA

Κατανεμημένα Συστήματα: Θεωρία και Προγραμματισμός. Ενότητα # 8: Ταυτοχρονισμός και νήματα Διδάσκων: Γεώργιος Ξυλωμένος Τμήμα: Πληροφορικής

Ειδικά Θέματα Προγραμματισμού

Διεργασίες (Processes)

Διδάσκων: Παναγιώτης Ανδρέου

Προγραμματισμός ΙΙ (Java) 10. Πολυνηματικές εφαρμογές Τεκμηρίωση κώδικα

Κινητά και Διάχυτα Συστήματα. Ενότητα # 3: Νήματα και ταυτοχρονισμός Διδάσκων: Γεώργιος Ξυλωμένος Τμήμα: Πληροφορικής

Πολυνηµατικές εφαρµογές σε Java

Αντικειµενοστρεφής Προγραµµατισµός

Διάλεξη 3: Προγραμματισμός σε JAVA I. Διδάσκων: Παναγιώτης Ανδρέου

Αντικειμενοστρεφής Προγραμματισμός

Εκφωνήσεις ασκήσεων εργαστηρίου 2 (java threads)

2.1 Αντικειµενοστρεφής προγραµµατισµός

Το πρόγραμμα HelloWorld.java. HelloWorld. Κλάσεις και Αντικείμενα (2) Ορισμός μιας Κλάσης (1) Παύλος Εφραιμίδης pefraimi <at> ee.duth.

13. Νήματα Νήματα και χρήση νημάτων στη Java Τι είναι τα νήματα; Τρία μέρη ενός νήματος

Διεργασίες (μοντέλο μνήμης & εκτέλεσης) Προγραμματισμός II 1

08 Πολυνηματικός προγραμματισμός στο JVM

Κατανεμημένα Συστήματα

Διεργασίες (μοντέλο μνήμης & εκτέλεσης) Προγραμματισμός II 1

Λειτουργικά Συστήματα Η/Υ

Εισαγωγή στα Λειτουργικά Συστήματα

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Αναφορές

ΠΛΗΡΟΦΟΡΙΚΗ Ι JAVA Τμήμα θεωρίας με Α.Μ. σε 3, 7, 8 & 9 22/11/07

Κεφάλαιο 1. Νήματα (Threads). Time Sharing

Ελεγκτές/Παρακολουθητές (Monitors) Ταυτόχρονος Προγραμματισμός 1

Διάλεξη 5: Κλάσεις και Αντικείμενα. Διδάσκων: Παναγιώτης Ανδρέου

Εισαγωγή στη γλώσσα προγραμματισμού JAVA. Δομές Δεδομένων Διδάσκων: Π.Α. Μήτκας Τομέας Ηλεκτρονικής και Υπολογιστών

ΠΛΗΡΟΦΟΡΙΚΗ ΙI Ενότητα 3: Έλεγχος ροής προγράμματος

Εργαστήριο 14. Συγχρονισμός Νημάτων (χρήση pthread_mutex_t, pthread_cond_t)

Εισαγωγή στον Αντικειμενοστρέφή Προγραμματισμό Διάλεξη #13

Κλάσεις και Αντικείµενα

ΠΛΗΡΟΦΟΡΙΚΗ ΙΙ (JAVA) 11/3/2008

Διδάσκων: Παναγιώτης Ανδρέου

Διάλεξη 08: Λίστες ΙΙ Κυκλικές Λίστες

Ταυτοχρονισμός (concurrency)

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Δημιουργώντας δικές μας Κλάσεις και Αντικείμενα

Μάθημα 3 ο ΔΙΕΡΓΑΣΙΕΣ (PROCESSES)

Κλάσεις στη Java. Παύλος Εφραιμίδης. Java Κλάσεις στη Java 1

Εισαγωγικά & Βασικές Έννοιες

Κλάσεις στη Java. Στοίβα - Stack. Δήλωση της κλάσης. ΗκλάσηVector της Java. Ηκλάση Stack

ΠΛΗΡΟΦΟΡΙΚΗ Ι JAVA Τμήμα θεωρίας με Α.Μ. σε 3, 7, 8 & 9 6/12/07

Κληρονομικότητα. Παύλος Εφραιμίδης pefraimi <at> ee.duth.gr. Java Κληρονομικότητα 1

HelloWorld. Παύλος Εφραιμίδης. Java Το πρόγραμμα HelloWorld 1

Dr. Garmpis Aristogiannis - EPDO TEI Messolonghi

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Μέθοδοι

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Δημιουργία Κλάσεων και Αντικειμένων

Υποστήριξη Λ.Σ. ΜΥΥ-106 Εισαγωγή στους Η/Υ και στην Πληροφορική

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Αντικείμενα με πίνακες. Constructors. Υλοποίηση Στοίβας

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Πίνακες Κλάσεις και Αντικείμενα

Αντικειμενοστραφής Προγραμματισμός I (5 ο εξ) Εργαστήριο #2 ο : Ανατομία προγραμμάτων εφαρμογών, η

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Αναφορές Στοίβα και Σωρός Αναφορές-Παράμετροι

ΚΕΦΑΛΑΙΟ 9. Ταυτόχρονος προγραμματισμός και νήματα. 9.1 Εισαγωγή

Συγχρονισμός Μέρος Α : Κρίσιμο τμήμα και κλειδώματα

Βασικά Στοιχεία της Java

Αντικειμενοστραφής Προγραμματισμός I(5 ο εξ) Εργαστήριο #2 ο : Ανατομία προγραμμάτων εφαρμογών, η

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα

Λειτουργικά Συστήματα

Διάλεξη 20: Αναδρομή (Recursion) Διδάσκων: Παναγιώτης Ανδρέου

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Μέθοδοι

Παύλος Εφραιµίδης. Java. Κληρονοµικότητα

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Αντικείμενα ως ορίσματα Εισαγωγή στις αναφορές

ιεργασίες και νήµατα Προγραµµατισµός ΙΙΙ 1 lalis@inf.uth.gr

Διάλεξη 16-17: Πολυμορφισμός (Polymorphism) Διδάσκων: Παναγιώτης Ανδρέου

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Αναφορές Στοίβα και Σωρός Μνήμης Αντικείμενα ως ορίσματα

Wrapper Classes, Abstract Classes and Interfaces

Αντικειμενοστρεφής Προγραμματισμός Διάλεξη 2 : ΜΕΤΑΒΛΗΤΕΣ ΤΕΛΕΣΤΕΣ & ΕΚΦΡΑΣΕΙΣ ΕΛΕΓΧΟΣ ΡΟΗΣ

3 Αλληλεπίδραση Αντικειμένων

Διδάσκων: Παναγιώτης Ανδρέου

I (JAVA) Ονοματεπώνυμο: Α. Μ.: Δώστε τις απαντήσεις σας ΕΔΩ: Απαντήσεις στις σελίδες των ερωτήσεων ΔΕΝ θα ληφθούν υπ όψην.

Οντοκεντρικός Προγραμματισμός

Αντικειμενοστρέφεια. Henri Matisse, Harmony in Red, Κωστής Σαγώνας Νίκος Παπασπύρου

Παράλληλη Επεξεργασία

Ελεγκτές/Παρακολουθητές (Monitors) Ταυτόχρονος Προγραμματισμός 1

ΠΛΗΡΟΦΟΡΙΚΗ Ι JAVA Τμήμα θεωρίας με Α.Μ. σε 3, 7, 8 & 9 25/10/07

Κρίσιμη Περιοχή Υπό Συνθήκη (Conditional Critical Regions) Ταυτόχρονος Προγραμματισμός 1

Βασικά Στοιχεία της Java

Προβλήματα ταυτόχρονης εκτέλεσης (για νήματα με κοινή μνήμη)

Εαρινό. Ύλη εργαστηρίου, Ασκήσεις Java

Γενικά (για τις γραπτές εξετάσεις)

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Εισαγωγή στη Java

Λειτουργικά Συστήματα

Βασικά της γλώσσας JAVA

Αντικειμενοστρεφής Προγραμματισμός Διάλεξη 4 : CLASSES

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Πολυμορφισμός Αφηρημένες κλάσεις Interfaces (διεπαφές)

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Μέθοδοι

Java Μέρος Ι Αντικειμενοστρεφής Προγραμματισμός - 7

Αντικειμενοστρεφής Προγραμματισμός

16. Multithreading (Java Applications)

Εισαγωγικά & Βασικές Έννοιες

Προβλήματα ταυτόχρονης εκτέλεσης (για νήματα με κοινή μνήμη)

ΤΕΧΝΙΚΕΣ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΑΦΟΥΣ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΥ. Κλάσεις και Αντικείμενα Μέθοδοι

Transcript:

Διάλεξη 22: Συγχρονισμός (Concurrency) Στην ενότητα αυτή θα μελετηθούν τα εξής επιμέρους θέματα: - Διεργασίες (processes) και Νήματα (threads) - Συγχρονισμός Νημάτων, Προβλήματα, Λύσεις - Οι τροποποιητές <synchronized>, <volatile> - Διαχείριση Συγχρονισμού Διδάσκων: Παναγιώτης Ανδρέου ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 1

Εισαγωγή Τι είναι ένα νήμα? Νήμα αποκαλείται η ελάχιστη οντότητα επεξεργασίας που μπορεί να δρομολογηθεί από το λειτουργικό σύστημα. Σε κάποια λειτουργικά συστήματα αποκαλούνται και Lightweight Processes Ποίο είναι το πιο κοινό πρόβλημα που μπορεί να προκύψει με την ταυτόχρονη εκτέλεση διεργασιών? Η ταυτόχρονη πρόσβαση σε κοινούς πόρους του συστήματος Πως αντιμετωπίζεται? Με τεχνικές αμοιβαίου αποκλεισμού των προσβάσεων. Ποια λύση προτείνεται από την Java? Αρκετές, ανάμεσα στις οποίες είναι οι: Synchronizedmethods, Synchronized blocks, Atomic access, Locks, ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 2

Νήματα (Threads) Το νήμα (thread)αποτελεί μία μοναδική, ακολουθιακή ροή ελέγχου μέσα σε ένα πρόγραμμα. Στα σύγχρονα συστήματα βρίσκονται σχεδόν σε όλες τις εφαρμογές (π.χ., DOS vs. Windows) Τα threads μπορούν να τρέχουν σε ένα υπολογιστή ή σε πολλαπλούς υπολογιστές Πολλαπλά threads Πολλαπλά CPUs thread 1 thread 2 thread 3 CPU1 CPU2 CPU3 Πολλαπλά threads Ένα CPU thread 1 thread 2 thread 3 CPU1 CPU1 CPU1 CPU1 CPU1 t ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 3

Διεργασίες (processes) vs. Νήματα(threads) Στον συντρέχον προγραμματισμό (concurrent programming), υπάρχουν δύο βασικά είδη εκτέλεσης: διεργασίες και νήματα. Ένα σύστημα έχει τυπικά πολλά ενεργά processes and threads. Αν υπάρχει μόνο ένας επεξεργαστής, τότε ο χρόνος (και πόροι) του μοιράζονταιστα processes and threads μέσω της τεχνικής time slicing που παρέχεται από το λειτουργικό σύστημα. Διεργασία (process) Ένα process έχει το δικό της αυτοδύναμο περιβάλλον εκτέλεσης: ξεχωριστό κομμάτι μνήμης και προσωπικούς πόρους Μία εφαρμογή περιλαμβάνει ένα σύνολο από processes που συνεργάζονται Η επικοινωνία μεταξύ τους (εντός και εκτός του ίδιου συστήματος) γίνεται μέσω τεχνικών όπως Pipes και Sockets (Inter Process Communication (IPC) Στην JAVA, μία εφαρμογή τρέχει σαν ένα process αλλά μπορεί να δημιουργήσει περισσότερα processes μέσω της κλάσης ProcessBuilder Παράδειγμα: ProcessBuilder builder = new ProcessBuilder("calc.exe"); builder.start(); ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 4

Διεργασίες (processes) vs. Νήματα(threads)(συν.) Νήμα (thread) Τα threadsονομάζονται και lightweight processes. Τα processes και threads παρέχουν ένα περιβάλλον εκτέλεσης Ένα thread χρειάζεται (δεσμεύει και χρησιμοποιεί) πιο λίγους πόρους από ένα process. Τα threadsυπάρχουν μέσα σε ένα processκαι ένα process έχει τουλάχιστον ένα thread. Τα threads μοιράζονται τους πόρους μίας διεργασίας (μνήμη, αρχεία, κτλ.) Η πολυπλοκότητα τους βρίσκεται στο θέμα της επικοινωνίας Στην JAVA κάθε εφαρμογή ξεκινάει αρχικά με ένα thread (main thread) Αυτή μπορεί να ξεκινήσει πολλά άλλα threads Στα μοντέρνα συστήματα, υπάρχουν πολλαπλοί επεξεργαστές, ή και επεξεργαστές με πολλαπλούς πυρήνες που υποστηρίζουν πιο αποδοτική εκτέλεση του συντρέχων προγραμματισμού ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 5

Δημιουργία και Εκκίνηση threads Κάθε thread σχετίζεται με ένα αντικείμενο της κλάσης Thread Μία εφαρμογή μπορεί να δημιουργήσει threads με δύο τρόπους 1. Με τη δημιουργία ενός αντικειμένου που υλοποιεί την διαπροσωπεία (interface) Runnable Το interface Runnable ορίζει μία μέθοδο (run()) η οποία θα έχει τον κώδικα εκτέλεσης του συγκεκριμένου thread Το αντικείμενο Runnable περνάει σαν παράμετρος στον κατασκευαστή της Thread Παράδειγμα public class HelloRunnable implements Runnable { public void run() { System.out.println("Hello from a thread!"); public static void main(string args[]) { ( new Thread( new HelloRunnable() ) ).start(); ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 6

Δημιουργία και Εκκίνηση threads(συν.) 2. Με την δημιουργία ενός αντικειμένου που κληρονομεί από την Thread Η κλάση Thread υλοποιεί την Runnableαλλά η μέθοδος run δεν κάνει τίποτα. method does nothing. An application can subclass Thread, providing its own implementation of run Παράδειγμα public class HelloThread extends Thread{ public void run() { System.out.println("Hello from a thread!"); public static void main(string args[]) { (new HelloThread()).start(); Ο πρώτος τρόπος είναι πιο γενικός και επίσης επιτρέπει την κληρονομικότητα από άλλες κλάσεις εκτός του Thread ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 7

H κλάση Thread Πιο σημαντικοί Κατασκευαστές Thread(): Δημιουργία ενός thread Thread(Runnable target): Δημιουργία thread για κάποιο task Πιο σημαντικές Μεθόδοι void start(): εκκίνηση ενός thread void yield(): επιτρέπει σε άλλα threads να τρέξουν πρώτα void sleep(long millis): το thread κοιμάται για κάποιο χρόνο void setpriority(int newp): αλλαγή προτεραιότητας (1..10) void interrupt(): διακόπτει το thread void join(): περιμένει μέχρι το thread να τελειώσει την εκτέλεσή booleanisalive(), isinterrupted():επιστρέφουν την κατάσταση του thread (π.χ., αν τρέχει, αν είναι τύπου daemon, αν έχει διακοπεί) void wait(): το thread μπαίνει σε κατάσταση waiting μέχρι να γίνει notify()ή notifyall() ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 8

Παράδειγμα: Δημιουργία και Εκκίνηση threads public class TaskThreadDemo { public static void main(string[] args) { Runnable printa = new PrintChar('a', 10); Runnable printb = new PrintChar('b', 10); Runnable print10 = new PrintNum(10); Thread thread1 = new Thread(printA); Thread thread2 = new Thread(printB); Thread thread3 = new Thread(print10); thread1.start(); thread2.start(); thread3.start(); class PrintChar implements Runnable { private char chartoprint; // character to print private int times; // The times to repeat public PrintChar(char c, int t) { chartoprint = c; times = t; //Override the run() method public void run() { for (int i = 0; i < times; i++) { System.out.println(charToPrint); class PrintNum implements Runnable { private int lastnum; public PrintNum(int n) { lastnum = n; public void run() { for (int i = 1; i <= lastnum; i++) { System.out.println(" " + i); Δημιουργία tasks: Αντικείμενα κλάσεων που υλοποιούν την Runnable Δημιουργία threads: Πέρασμα στον κατασκευαστή της Thread των αντικειμένων που υλοποιούν την Runnable Εκκίνηση των 3 threads Υλοποίηση της διαπροσωπείας Runnable από δύο κλάσεις Υπερκάλυψη (override) της μεθόδου run() ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 9

Συγχρονισμός Νημάτων (Thread Synchronization) Τα νήματα επικοινωνούν μεταξύ τους μέσω κοινών πόρων (π.χ., μία μεταβλητή) Αυτή η μορφή επικοινωνίας είναι πολύ αποδοτική γιατί δεν χρειάζεται η δημιουργία αντιγράφων των κοινών πόρων Όμως, μπορεί να παρουσιάσει δύο είδη προβλημάτων: Παρεμβολές (Thread Interference):δύο threads έχουν πρόσβαση στα ίδια δεδομένα ταυτόχρονα Λάθη Ασυνέπειας στην Μνήμη (Memory Consistency Errors): όταν υπάρχουν ασυνέπειες στην όψη της μνήμης, π.χ., παρουσίαση δύο διαφορετικών τιμών για την ίδια μεταβλητή Η λύση για να αποφύγουμε αυτά τα προβλήματα είναι ο συγχρονισμός ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 10

Παράδειγμα Παρεμβολών (Thread Interference) class Counter { private int c = 0; public int getvalue() { return c; public void setvalue(int newc) { c=newc; Οι παρεμβολές συμβαίνουν υπάρχουν περισσότερα το ενός βημάτων σε πολλαπλά threads και αυτά υπερκαλύπτονται μεταξύ τους public class Main { public static void main(string[] args) { final Counter c = new Counter(); (new Thread( new Runnable() { public void run() { int x = c.getvalue(); x = x + 1; c.setvalue(x); )).start(); (new Thread( new Runnable() { public void run() { int x = c.getvalue(); x = x - 1; c.setvalue(x); )).start(); Thread A Thread B Σενάριο 1. Thread A: Ανάκτηση του c 2. Thread B: Ανάκτηση του c 3. Thread A: Αύξηση του x(x=1) 4. Thread Β: Μείωση του x(x=-1) 5. Thread A: Αποθήκ. του x(c=1) 6. Thread B: Αποθήκ. του x(c=-1) 7. Thread A: (Πρόβλημα) ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 11

Παράδειγμα Λάθη Ασυνέπειας στην Μνήμη class Counter { private int c = 0; public void increment() { c++; Object o = new Object(); public void decrement() { c--; public void value() { System.out.println("c="+c); public class Main { public static void main(string[] args) { final Counter c = new Counter(); (new Thread( new Runnable() { public void run() { c.increment(); c.value(); )).start(); (new Thread( new Runnable() { public void run() { c.decrement(); c.value(); )).start(); Thread A Thread B Οι ασυνέπειες συμβαίνουν όταν τα νήματα έχουν διαφορετικές όψεις των ίδιων δεδομένων Πιθανές εκδοχές εκτύπωσης του διπλανού προγράμματος: c=1, c=0 (Σωστό) c=-1, c=0(λάθος) c=0, c=0(λάθος) c=-1, c=1 (Μπορεί να γίνει;;;) Μπορούν να αποφευχθούν (όχι πάντα) με την χρήση της σχέσης (happens-before) ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 12

Προσδιοριστής <synchronized> Στα προηγούμενα παραδείγματα, παρουσιάζεται πρόβλημα επειδή δύο threads έχουν πρόσβαση και μεταβάλλουν τον ίδιο πόρο Το πρόβλημα αυτό ονομάζεται race condition Για να αποφύγουμε τα race conditions μπορούμε να χρησιμοποιήσουμε τον προσδιοριστή synchronized thread-safe κώδικας synchronized: κανένα thread δεν μπορεί να έχει πρόσβαση στους πόρους της εμβέλειας του ταυτόχρονα με το τρέχων thread Μπορεί να δηλωθεί στο πεδίο εμβέλειας μίας μεθόδου Όλοι οι πόροι που σχετίζονται με το αντικείμενο που βρίσκεται η μέθοδος κλειδώνεται (lock) μέχρι να τερματίσει η μέθοδος Μπορεί να δηλωθεί σε συγκεκριμένο πεδίο εμβέλειας κώδικα Μόνο οι πόροι (αντικείμενο) που καθορίζονται από το συγκεκριμένο πεδίο εμβέλειας κώδικα κλειδώνονται ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 13

Παράδειγμα <synchronized> μεθόδοι class SynchronizedCounter { private int c = 0; public synchronized void increment() { c++; public synchronized void decrement() { c--; public synchronized int value() { return c; Τι έχουμε πετύχει; Δεν υπάρχει περίπτωση υπερκάλυψης των μεθόδων του ίδιου αντικειμένου Όταν καλέσουμε μία μέθοδο, τότε αφού αυτή πρέπει να τελειώσει για να αφήσει το lock, έχουμε πετύχει αυτόματα την σχέση happens-before, δηλ. ότι μέθοδος ακολουθήσει θα έχει την ίδια όψη αντικειμένου Απλή και αποδοτική μέθοδος ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 14

Συγχρονισμός συγκεκριμένων αντικειμένων Ο μηχανισμός του συγχρονισμού σχετίζεται με το κλείδωμα συγκεκριμένων αντικειμένων Όταν προσθέτουμε το synchronized σε μία μέθοδο σημαίνει ότι έμμεσα κλειδώνουμε το αντικείμενο που βρίσκεται στην μέθοδο Μερικές φορές όμως μπορεί να θέλουμε να κλειδώσουμε άλλα αντικείμενα Μπορούμε να το κάνουμε με την δήλωση: synchronize(object){ Ονομάζεται και synchronized block. Αν το αντικείμενο είναι ήδη κλειδωμένο από κάποιο άλλο thread Β τότε όταν καλεστεί η μέθοδος από το thread A θα πρέπει να περιμένει μέχρι να τελειώσει την εκτέλεση το thread B(ξεκλείδωμα) Παρατήρηση: Μία δήλωση synchronized method() { είναι ισοδύναμη με method() { synchronized(this) { ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 15

Συγχρονισμός με προστατευόμενα πλαίσια Συγχρονισμός με προστατευόμενα πλαίσια (guarded blocks) επιτυγχάνεται με τις εντολές wait(), notify() και notifyall() Δεν μπορούν ποτέ να υπερσκελιστούν(δηλώνονται final). Μπορούν να κληθούν μόνο μέσα από τομείς που δηλώνονται ως synchronized. Υλοποιούν τη λογική της αναμονής κάποιου γεγονότος το οποίο θα σηματοδοτηθεί από κάποιο άλλο Thread. Όταν ένα Threadεισέλθει σε κατάσταση wait, αναστέλλεται μέχρι να αφυπνιστεί από κάποιο άλλο Thread. Επίσης ελευθερώνει το αντικείμενο το οποίο είχε κλειδώσει όταν εισήλθε στο synchronized block. Η αφύπνιση του Threadπροκαλείται από κάποιο άλλο Threadτο οποίο έχει τα δικαιώματα πρόσβασης στο ίδιο αντικείμενο. ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 16

Συγχρονισμός με προστατευόμενα πλαίσια (συν.) Η αφύπνιση γίνεται με την εντολή notify() Όταν κληθεί η notify() το Threadπου είχε το δικαίωμα πρόσβασης το παραχωρεί στο Thread που είχε ανασταλεί στη συνάρτηση wait(). Προσοχή: Στη συνάρτηση notify() δε δηλώνουμε τι να αφυπνιστεί. Για το λόγο αυτό αν περιμένουν περισσότερα του ενός Threadδε ξέρουμε ποιο θα ξυπνήσει. Παρατηρήσεις Η notify() αφυπνίζει μόνο 1 thread. Η notifyall() αφυπνίζει όλα τα threads. Η εντολή notify() μπορεί μόνο να αφυπνίσει ένα Τhreadπου υπήρχε στην ουρά αναμονής. Η notify() είναι ασφαλής υπό 2 συνθήκες μόνο: Όταν και μόνο όταν υπάρχει ένα threadσε αναμονή. Όταν πολλά threadείναι σε αναμονή αλλά δεν υπάρχει ιδιαίτερη σημασία ποιο από όλα θα ξυπνήσει. ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 17

Παράδειγμα συγχρονισμού με guarded blocks Espresso Bar (Παραγωγή / Κατανάλωση) Χρησιμοποιούμε ένα πάγκο (buffer)όπου τοποθετούμε τα espressos που παράγει ο barrista. O πάγκος (buffer) έχει περιορισμένη χωρητικότητα (CAPACITY) Υπάρχει μία μεταβλητή count που μετράει τα διαθέσιμα espresso στον πάγκο O barristaέχει τη μέθοδο createespresso() που δημιουργεί ένα espressoκαι ο πελάτης την μέθοδο drinkespresso() που πίνει ένα espresso Δημιουργία Καφέ Παράδοση Καφέ while (count == CAPACITY) wait() while(count==0) wait() createespresso() drinkespresso() notifyall() notifyall() Ερώτηση: Χρειαζόμαστε τους βρόγχους while και τις συνθήκες τους; ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 18

Συγχρονισμός με locks Όπως έχουμε πει, μία synchronized μέθοδος έμμεσα κλειδώνει το στιγμιότυπο της κλάσης (αντικείμενο) πριν να εκτελέσει την μέθοδο Το JDK 1.5 (και αργότερα) επιτρέπουν στον προγραμματιστή να δημιουργήσει άμεσα τα locks Αυτό δίνει περισσότερη ευελιξία για τον έλεγχο και το συγχρονισμό threads Ένα lock είναι ένα στιγμιότυπο κλάσης που υλοποιεί την διαπροσωπεία java.util.concurrent.locks.lock Η διαπροσωπεία Lock δηλώνει μεθόδους για την δημιουργία και απελευθέρωση locks Επίσης, παρέχει την μέθοδο newcondition() για την δημιουργία προϋποθέσεων (αντικειμένων τύπου Condition) για την επικοινωνία και συντονισμό threads. Γνωστή κλάση που υλοποιεί την Lock είναι η ReentrantLockπου επιβάλει μία δίκαιη πολιτική locks ώστε να μην παρουσιάζονται προβλήματα starvation (π.χ., threads που περιμένουν το περισσότερο έχουν προτεραιότητα) ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 19

Συγχρονισμός με locks(συν.) Δημιουργία και αρχικοποίηση αντικειμένου τύπου Lock Lock lock = new ReentrantLock(); Μεθόδοι lock(), lockinterruptibly():απόκτηση lockκαι απόκτηση lock αν δεν έχει γίνει interrupt το τρέχον thread unlock(): απελευθέρωση του lock trylock(), trylock(long time, TimeUnitunit):προσπάθεια απόκτησης του lock αν είναι διαθέσιμο (και σε συγκεκριμένο χρονικό διάστημα) newcondition():δημιουργία καινούριας συνθήκες (επόμενη διαφάνεια) Παράδειγμα χρήσης σε μία μέθοδο lock.lock(); /* δηλώσεις */ lock.unlock(); ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 20

Συγχρονισμός με locks(συν.) Τα conditions χρησιμοποιούνται για επίτευξη επικοινωνίας μεταξύ threads Ένα thread μπορεί να προσδιορίσει τι θα κάνει κάτω από συγκεκριμένες συνθήκες Δημιουργούνται με την μέθοδο newcondition() σε Lock αντικείμενα Για την επικοινωνία χρησιμοποιούνται οι μεθόδοι: await():το thread περιμένει μέχρι η συνθήκη να γίνει σηματοδότηση (signal) signal():σηματοδοτεί ότι ένα thread που περιμένει πρέπει να ξύπνησε signalall(): Όπως το signal() αλλά όλα τα threads που περιμένουν await(long time, TimeUnit unit) long awaitnanos(long nanostimeout), void awaituninterruptibly(), boolean awaituntil(date deadline) ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 21

Συγχρονισμός με locks(συν.) Παράδειγμα BankAccount με διαδικασίες Κατάθεση/Ανάληψη Ανάληψη Κατάθεση lock.lock() lock.lock() while(balance<withdraw amount) newdeposit.await(); balance += withdraw Amount balance-= withdraw Amount newdeposit.signalall(); lock.unlock() lock.unlock() ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 22

Καταστάσεις ενός thread (java.lang.thread.state) new Thread() New (NEW) start() Sleeping (TIMED_WAITING) Timer expired Runnable (RUNNABLE) Access granted sleep() Scheduler Running (RUNNABLE) Access blocking resource (e.g., I/O) Blocking (BLOCKED) notify(), notifyall() Waiting (WAITING) wait(), yield run() completed or stop() Dead (TERMINATED) ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 23

Ατομική Πρόσβαση (Atomic Access) Ένας άλλος τρόπος για επίτευξη του συγχρονισμού είναι μέσα από τον καθορισμό ατομικών μεταβλητών Μία ατομική ενέργεια (atomic action)είναι μία ενέργεια η οποία συμβαίνει όλη την ίδια στιγμή, αλλιώς δεν συμβαίνει καθόλου, δηλ. δεν μπλοκάρει Τα atomic actionsδεν μπορούν να υπερκαλυφθούν γι αυτό και δεν μπορεί να υπάρξει πρόβλημα παρεμβολών Αυτό δεν σημαίνει ότι δεν μπορούν να υπάρξουν ασυνέπειες μνήμης γι αυτό και μπορεί να πρέπει να καθοριστούν σαν synchronized Χρησιμοποιώντας πρόσβαση ατομικών μεταβλητών είναι πιο αποδοτικό από synchronized κώδικα αλλά χρειάζονται περισσότερη προσπάθεια από τον προγραμματιστή Κάποιες από τις κλάσεις που βρίσκονται στην κεντρική βιβλιοθήκη του συγχρονισμού (java.util.concurrent)περιλαμβάνουν ατομικές μεθόδους που δεν βασίζονται στον συγχρονισμό. ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 24

Ατομική Πρόσβαση (Atomic Access)(συν.) Τα αντικείμενα και οι Αρχέγονοι τύποι μπορούν να δηλωθούν ως ατομικοί χρησιμοποιώντας τον τροποποιητή volatile Η λέξη κλειδί volatileενημερώνει τον compilerότι η συγκεκριμένη κατάσταση (μεταβλητή) θα έχει πρόσβαση από περισσότερα του ενός Threads. Η μεταβλητή που δηλώνεται volatileδεν αποθηκεύεται ποτέ στην cache του Thread. Διαφορές μεταξύ volatile και synchronized Χαρακτηριστικό synchronized volatile Τύπος Μεταβλητής Αντικείμενο Αντικείμενο, Αρχέγονοι Τύποι Επιτρέπεται το null; OXI NAI Μπορεί να μπλοκάρει; ΝΑΙ ΌΧΙ Πότε γίνεται ο συγχρονισμός; Κάλεσμα/Εκτέλεση της μεθόδου Πρόσβαση στην μεταβλητή Συνδυασμόςπολλαπλών λειτουργιών σε ένα ατομικό block NAI JAVA 1.4: OXI JAVA 1.5: NAI ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 25

Παράδειγμα τροποποιητή <volatile> public class VolatileTest { volatile boolean running = true; public void test() { new Thread(new Runnable() { public void run() { int counter = 0; while (running) { counter++; System.out.println("Thread 1 finished.counted up to "+counter); ).start(); new Thread(new Runnable() { public void run() { // Sleep for a bit so that thread 1 has a chance to start try { Thread.sleep(100); catch (InterruptedException ignored) { System.out.println("Thread 2 finishing"); running = false; ).start(); public static void main(string[] args) { new VolatileTest().test(); ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 26

Προβλήματα Συγχρονισμού Οι τεχνικές του συγχρονισμού μπορούν να μειώσουν κατά πολύ τα προβλήματα των παρεμβολών και της ασυνέπειας μνήμης Φυσικά, αυτό εναπόκειται και στις προγραμματιστικές ιδιότητες του προγραμματιστή Παρουσιάζουν όμως κάποια άλλα προβλήματα τα οποία έχουν σχέση με την ζωή των threads Τα πιο σημαντικά προβλήματα συγχρονισμού είναι: (Νεκρό) Αδιέξοδο (Deadlock):Κάθε thread περιμένει ανενεργά ένα lock από κάποιο άλλο thread που με τη σειρά του περιμένει ένα lock από άλλο thread(διαδοχικά μέχρι το πρώτο thread) Λιμοκτονία (Starvation):κάποια thread περιμένουν για μεγάλα χρονικά διαστήματα κάποιους locked πόρους Ζωντανό Αδιέξοδο (Livelock):το ίδιο με το deadlock αλλά τα threads είναι ενεργά ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 27

Παράδειγμα Προβλημάτων Συγχρονισμού DeadLock Αλγόριθμος περάσματος διαδρόμου: 1. Αν έχει κάποιο απέναντι σου στην ίδια λωρίδα, τότε περίμενε μέχρι να μετακινηθεί 2. Αλλιώς προχώρησε μπροστά Αποτέλεσμα: καμία μετακίνηση από τα δύο άτομα, ποτέ! LiveLock Αλγόριθμος περάσματος διαδρόμου: 1. Αν έχει κάποιο απέναντι σου στην ίδια λωρίδα, μετακινήσου στην άλλη λωρίδα 2. Αλλιώς προχώρησε μπροστά Αποτέλεσμα: συνεχής μετακίνηση αριστερά-δεξιά από τα δύο άτομα Starvation Αλγόριθμος διεκπεραίωσης παραγγελιών εστιατορίου: ΔΙΑΔΡΟΜΟΣ 1. Κάθε χρονική στιγμή επέλεγε την παραγγελία που κοστίζει περισσότερο Αποτέλεσμα:Υποθέτοντας μία παραγγελία το λεπτό και χρόνο διεκπεραίωσης > του ενός λεπτό η παραγγελία με το πιο μικρό κόστος θα εξυπηρετηθεί τελευταία ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 28

Διαχείριση Συγχρονισμού Τα προηγούμενα παραδείγματα τρέχουν αποδοτικά για μικρές εφαρμογές Σε μεγάλες εφαρμογές είναι καλύτερα να διαχωρίζεται η διαχείριση των threads από την υπόλοιπη εφαρμογή (π.χ., Web Server) Τα υπεύθυνα αντικείμενα για την διαχείριση των threads είναι οι εκτελεστές (executors) Στην βιβλιοθήκη java.util.concurrent ορίζονται 3 executor interfaces: Executor:υποστηρίζει την δημιουργία και εκτέλεση καινούριων threads ExecutorService:,ελέγχει τον κύκλο ζωής ενός executor και των threads του. ScheduledExecutorService:υποστηρίζει την περιοδική εκτέλεση των threads ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 29

Παράδειγμα Διαχείρισης Συγχρονισμού import java.util.concurrent.*; public class ExecutorDemo { public static void main(string[] args) { // Create a fixed thread pool with maximum three threads ExecutorService executor = Executors.newFixedThreadPool(3); // Submit runnable tasks to the executor executor.execute(new PrintChar('a', 100)); executor.execute(new PrintChar('b', 100)); executor.execute(new PrintNum(100)); // Shut down the executor executor.shutdown(); ΕΠΛ233 Αντικειμενοστρεφής Προγραμματισμός 30