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

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

Προβλήματα Συγχρονισμού (με ελεγκτή) Ταυτόχρονος Προγραμματισμός 1

Προβλήματα Συγχρονισμού (με ελεγκτή) Ταυτόχρονος Προγραμματισμός 1

Υλοποίηση Σηματοφόρων

Σηματοφόροι (Σηματοφορείς) Ταυτόχρονος Προγραμματισμός 1

Σηματοφόροι (Σηματοφορείς) Ταυτόχρονος Προγραμματισμός 1

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

Κλασικά Προβλήματα Συγχρονισμού (με σηματοφόρους) Ταυτόχρονος Προγραμματισμός 1

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

Συγχρονισμός & σηματοφόροι. Προγραμματισμός II 1

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

Αμοιβαίος αποκλεισμός με κοινή μνήμη. Ταυτόχρονος Προγραμματισμός 1

Αμοιβαίος αποκλεισμός με κοινή μνήμη. Ταυτόχρονος Προγραμματισμός 1

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

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

Ορθότητα λειτουργίας τμημάτων λογισμικού & δομών δεδομένων υπό ταυτόχρονη εκτέλεση

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

Ορθότητα λειτουργίας τμημάτων λογισμικού & δομών δεδομένων υπό ταυτόχρονη εκτέλεση

Αμοιβαίος αποκλεισμός με κοινή μνήμη. Ταυτόχρονος Προγραμματισμός 1

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

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

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

Dr. Garmpis Aristogiannis - EPDO TEI Messolonghi

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

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

Επικοινωνία µεταξύ ιεργασιών και Σύνδροµες ιεργασίες

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

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

Δείκτες σε συναρτήσεις. Προγραμματισμός II 1

Χώροι Πλειάδων (Tuple Spaces) Ταυτόχρονος Προγραμματισμός 1

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

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

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

Προσπέλαση σύνθετων δομών δεδομένων χωρίς καθολικό κλείδωμα

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

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

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

Το μάθημα. Λειτουργικά Συστήματα Πραγματικού Χρόνου Βασικές Έννοιες 6. Ενσωματωμένα Συστήματα (embedded systems) Παραδείγματα

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

Λειτουργικά Συστήματα Πραγματικού Χρόνου

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

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

Προσπέλαση σύνθετων δομών δεδομένων χωρίς καθολικό κλείδωμα

2.4 Κλασσικά Προβλήματα IPC

Χώροι Πλειάδων (Tuple Spaces) Ταυτόχρονος Προγραμματισμός 1

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

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

Σύγχρονη επικοινωνία με ανταλλαγή μηνυμάτων (CSP message passing model) Ταυτόχρονος Προγραμματισμός 1

Εντοπισμός αδιεξόδου. Κατανεμημένα Συστήματα 1

Εισαγωγή στον Προγραµµατισµό, Αντώνιος Συµβώνης, ΣΕΜΦΕ, ΕΜΠ,, Slide 6

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

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

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

Δομές Δεδομένων & Αλγόριθμοι

Θοδωρής Ανδρόνικος Τμήμα Πληροφορικής, Ιόνιο Πανεπιστήμιο

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

Αμοιβαίος αποκλεισμός

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

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

Συστηματικός έλεγχος ορθότητας ταυτόχρονων προγραμμάτων μέσω γράφου καταστάσεων

Συστηματικός έλεγχος ορθότητας ταυτόχρονων προγραμμάτων μέσω γράφου καταστάσεων

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

Βασικές Έννοιες Πρ Ταο υγρ τόα χ μ ρ μ ο α ν τισμ ος Π ό ρ ςο ΙΙΙ γραμματισμός 1

Συλλογές, Στοίβες και Ουρές

Δομές Δεδομένων & Ανάλυση Αλγορίθμων. 3ο Εξάμηνο. Ουρά (Queue) Υλοποίηση της με τη βοήθεια πίνακα.

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

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

Το λειτουργικό σύστημα. Προγραμματισμός II 1

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

Εθνικό Μετσόβιο Πολυτεχνείο Σχολή Ηλεκτρολόγων Μηχ. και Μηχανικών Υπολογιστών Εργαστήριο Υπολογιστικών Συστημάτων. Συγχρονισμός

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

Εθνικό Μετσόβιο Πολυτεχνείο Σχολή Ηλεκτρολόγων Μηχ. και Μηχανικών Υπολογιστών Εργαστήριο Υπολογιστικών Συστημάτων. Συγχρονισμός

Διάλεξη 10: Αλγόριθμοι Αμοιβαίου Αποκλεισμού σε περιβάλλον ανταλλαγής μηνυμάτων. ΕΠΛ 432: Κατανεμημένοι Αλγόριθμοι

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

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

Δημιουργία & Τερματισμός Διεργασιών. Προγραμματισμός II 1

Διάλεξη 9: Αλγόριθμοι Αμοιβαίου Αποκλεισμού με τη χρήση μεταβλητών Ανάγνωσης/Εγγραφής. ΕΠΛ 432: Κατανεμημένοι Αλγόριθμοι

Διάλεξη 8: Πρόβλημα Αμοιβαίου Αποκλεισμού. ΕΠΛ 432: Κατανεμημένοι Αλγόριθμοι

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

Εικονική Μνήμη (Virtual Memory) Προγραμματισμός II 1

Σύγχρονη επικοινωνία με ανταλλαγή μηνυμάτων (CSP message passing model) Ταυτόχρονος Προγραμματισμός 1

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

2 Ορισμός Κλάσεων. Παράδειγμα: Μηχανή για Εισιτήρια. Δομή μιας Κλάσης. Ο Σκελετός της Κλάσης για τη Μηχανή. Ορισμός Πεδίων 4/3/2008

Δομές Δεδομένων (Data Structures)

Μάθημα 4 ο. Κρίσιμα Τμήματα και Αμοιβαίος Αποκλεισμός

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

Όταν το πρόγραμμα φτάσει σε αυτή την εντολή και ο καταχωρητής PINA έχει την τιμή

Αδιέξοδα (Deadlocks)

Βασικές Έννοιες Δοµών Δεδοµένων

Το λειτουργικό σύστημα. Προγραμματισμός II 1

Νήµατα. Πολύ σηµαντικό

Προγραμματισμός Η/Υ (ΤΛ2007 )

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

Ιδιοκτησία Αντικειµένου

ΔΙΕΡΓΑΣΙΕΣ. Λειτουργικά Συστήματα Ι. Διδάσκων: Καθ. Κ. Λαμπρινουδάκης ΛΕΙΤΟΥΡΓΙΚΑ ΣΥΣΤΗΜΑΤΑ Ι

Εντολές επιλογής Επαναλήψεις (if, switch, while)

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

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

Στόχοι και αντικείμενο ενότητας. Προτάσεις επανάληψης. Έλεγχος ροής προγράμματος. #5.. Εντολές Επανάληψης

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

Transcript:

Ελεγκτές/Παρακολουθητές (Monitors) 1 lalis@inf.uth.gr

Ελεγκτές Αμοιβαίος αποκλεισμός στο πλαίσιο ενός τμήματος λογισμικού που προσπελάζεται με δομημένο τρόπο, μέσω προκαθορισμένης διασύνδεσης (API) Ο συγχρονισμός γίνεται την στιγμή που ένα νήμα επιχειρεί να καλέσει μια λειτουργία του ελεγκτή Αν κάποιο άλλο νήμα ήδη εκτελεί μια λειτουργία του ελεγκτή, το καλών νήμα μπλοκάρεται μέχρι το προηγούμενο νήμα να ολοκληρώσει την λειτουργία Ο αμοιβαίος αποκλεισμός είναι εξ ορισμού εγγυημένος για κώδικα που γράφεται μέσα στο πλαίσιο ενός ελεγκτή 2 lalis@inf.uth.gr

entry points mutual exclusion boundary proc3 proc2 proc1 code code code state / data Monitor 3 lalis@inf.uth.gr

proc2 proc1 proc2 proc1 code code (1) (2) state / data code state / data code proc2 proc1 proc2 proc1 code code (3) (4) state / data code state / data code 4 lalis@inf.uth.gr

Δομή κώδικα monitor name { /* δηλώσεις μεταβλητών */ /* ρουτίνες πρόσβασης ελεγκτή */ proc1 ( ) { proc2 ( ) { εκτελούνται με εγγυημένο τον αμοιβαίο αποκλεισμό procν ( ) { 5 lalis@inf.uth.gr

Κρίσιμο τμήμα monitor cs { void CS1 () { /* κώδικας που αποτελεί κρίσιμο τμήμα */ void CSN() { /* κώδικας που αποτελεί κρίσιμο τμήμα */ : : PN: while (1) { cs.cs1(); while (1) { cs.cs2();... while (1) { cs.csn(); 6 lalis@inf.uth.gr

με ελεγκτή monitor counter { int cnt; void init() { cnt=0; με δυαδικό σηματοφόρο int cnt; bsem mtx; void init() { cnt=0; init(mtx,1); void inc() { cnt=cnt+1; void dec() { cnt=cnt-1; void inc() { down(mtx); cnt=cnt+1; up(mtx); void dec() { down(mtx); cnt=cnt-1; up(mtx); 7 lalis@inf.uth.gr

Μεταβλητές συνθήκης Συχνά απαιτείται αναμονή υπό συνθήκη μέσα σε ένα κρίσιμο τμήμα π.χ., αναμονή καταναλωτή όταν/όσο η αποθήκη είναι άδεια Η αναμονή μέσα σε ελεγκτή επιτυγχάνεται με μεταβλητές συνθήκης (condition variables) Η μεταβλητή συνθήκης μπορεί να θεωρηθεί ως μια δίκαιη ουρά αναμονής Οι μεταβλητές συνθήκης μπορεί να δηλωθούν μόνο μέσα σε έναν ελεγκτή δεν είναι σηματοφόροι 8 lalis@inf.uth.gr

Χρήση μεταβλητών συνθήκης : δήλωση wait(x): το καλών νήμα μπλοκάρεται, ενώ παράλληλα αίρεται ο «συμβατικός» αμοιβαίος αποκλεισμός στον ελεγκτή (γιατί;) signal(x): αφυπνίζεται ένα (το πρώτο) από τα νήματα που έχουν μπλοκάρει στο x Αν δεν υπάρχει μπλοκαρισμένο νήμα στο x, απλά δεν γίνεται τίποτα αν στη συνέχεια ένα νήμα καλέσει wait(x), θα μπλοκάρει 9 lalis@inf.uth.gr

Συνθήκες ανταγωνισμού Με σηματοφόρους, αν ένα νήμα επιθυμεί να περιμένει μέσα στο ΚΤ, πρέπει να απελευθερώσει (up) τον σηματοφόρο που χρησιμοποιείται για αμοιβαίο αποκλεισμό, και να μπλοκάρει (down) μειώνοντας τον σηματοφόρο που χρησιμοποιείται ως ουρά αναμονής Υπάρχει η «κλασική» συνθήκη ανταγωνισμού: πιθανότητα εναλλαγής μετά το up και πριν το down Αυτό το πρόβλημα δεν υφίσταται σε ελεγκτή (όμως: βλέπε ζητήματα προτεραιότητας) 10 lalis@inf.uth.gr

bsem mtx,q; void init() { init(mtx,1); init(q,0); void proc1( ) { down(mtx); if ( ) { up(mtx); else { up(mtx); down(q); monitor { condition q; void init() { void proc1( ) { if ( ) { wait(q); δεν υφίσταται συνθήκη ανταγωνισμού void proc2( ) { down(mtx); if ( ) { up(q); up(mtx); υπάρχει συνθήκη ανταγωνισμού void proc2( ) { if ( ) { signal(q); 11 lalis@inf.uth.gr

Προτεραιότητες (1) Τι γίνεται αν ένα νήμα μέσω signal αφυπνίσει ένα άλλο νήμα που έχει μπλοκάρει μέσα στον ελεγκτή; Για να ισχύει αμοιβαίος αποκλεισμός, μόνο ένα νήμα μπορεί να συνεχίσει την εκτέλεση του στον ελεγκτή signal-continue: προτεραιότητα έχει το νήμα που προκάλεσε την αφύπνιση (κάλεσε την signal) signal-block: προτεραιότητα έχει το νήμα που αφυπνίστηκε (σειρά εισόδου στον ελεγκτή) Δεν τίθεται θέμα αν η signal καλείται ως τελευταία εντολή σε μια ρουτίνα του ελεγκτή γιατί; 12 lalis@inf.uth.gr

πλαίσιο συγχρονισμού του ελεγκτή ουρά αναμονής της μεταβλητής συνθήκης x νήμα που εκτελεί κώδικα του ελεγκτή ουρά νημάτων που περιμένουν, λόγω signal&block / signal&continue, να ελευθερωθεί ο ελεγκτής 13 lalis@inf.uth.gr

call 14 lalis@inf.uth.gr

15 lalis@inf.uth.gr

wait 16 lalis@inf.uth.gr

17 lalis@inf.uth.gr

call 18 lalis@inf.uth.gr

19 lalis@inf.uth.gr

signal 20 lalis@inf.uth.gr

signal-continue signal 21 lalis@inf.uth.gr

signal-continue προσπεράστηκε από 22 lalis@inf.uth.gr

signal-continue exit 23 lalis@inf.uth.gr

signal-continue 24 lalis@inf.uth.gr

signal-continue 25 lalis@inf.uth.gr

signal 26 lalis@inf.uth.gr

signal-block signal 27 lalis@inf.uth.gr

signal-block 28 lalis@inf.uth.gr

signal-block exit 29 lalis@inf.uth.gr

signal-block 30 lalis@inf.uth.gr

signal-block 31 lalis@inf.uth.gr

Προτεραιότητες (2) Τι γίνεται με τα νήματα που έχουν μπλοκάρει έξω από τον ελεγκτή, περιμένοντας να τους δοθεί άδεια να προχωρήσουν με την εκτέλεση μιας λειτουργίας; Eggshell: προτεραιότητα έχουν τα νήματα που ήδη έχουν αρχίσει την εκτέλεση τους μέσα στον ελεγκτή Λογική FIFO Open: τα νήματα έχουν την ίδια προτεραιότητα Ένα νήμα που αφυπνίζει/αφυπνίζεται μέσω signal, μπορεί προσπεραστεί από ένα άλλο νήμα που περιμένει έξω από τον ελεγκτή 32 lalis@inf.uth.gr

Eggshell χαμηλή προτεραιότητα ουρά εισόδου ουρά αναμονής της μεταβλητής συνθήκης x ψηλή προτεραιότητα νήμα που εκτελεί κώδικα του ελεγκτή ουρά νημάτων που περιμένουν, λόγω signal&block / signal&continue, να ελευθερωθεί ο ελεγκτής 33 lalis@inf.uth.gr

eggshell P3 call 34 lalis@inf.uth.gr

P3 eggshell 35 lalis@inf.uth.gr

P3 eggshell signal-block signal 36 lalis@inf.uth.gr

P3 eggshell 37 lalis@inf.uth.gr

P3 eggshell exit 38 lalis@inf.uth.gr

P3 eggshell 39 lalis@inf.uth.gr

P3 eggshell 40 lalis@inf.uth.gr

P3 eggshell exit 41 lalis@inf.uth.gr

P3 eggshell 42 lalis@inf.uth.gr

P3 eggshell 43 lalis@inf.uth.gr

eggshell P3 44 lalis@inf.uth.gr

Open κοινή ουρά (α) για τα νήματα που θέλουν να μπουν στον ελεγκτή και (β) για τα νήματα που είχαν μπλοκάρει λόγω signal μέσα στον ελεγκτή ουρά εισόδου ουρά αναμονής της μεταβλητής συνθήκης x νήμα που εκτελεί κώδικα του ελεγκτή 45 lalis@inf.uth.gr

open call P3 46 lalis@inf.uth.gr

P3 open 47 lalis@inf.uth.gr

P3 open signal-block signal 48 lalis@inf.uth.gr

P3 open προσπεράστηκε από το P3 49 lalis@inf.uth.gr

P3 open exit 50 lalis@inf.uth.gr

P3 open 51 lalis@inf.uth.gr

open P3 52 lalis@inf.uth.gr

Συνθήκη ανταγωνισμού Ο μηχανισμός του ελεγκτή λύνει το πρόβλημα της συνθήκης ανταγωνισμού σε περίπτωση που ένα νήμα επιθυμεί να μπλοκάρει μέσα στον ελεγκτή Δεν υπάρχει περίπτωση να παρεμβληθεί άλλο νήμα ανάμεσα στον έλεγχο της συνθήκης αναμονής και την κλήση της wait Παρόλα αυτά, πάλι μπορεί να υπάρχουν συνθήκες ανταγωνισμού, ανάλογα με το μοντέλο προτεραιότητας της υλοποίησης του ελεγκτή Το eggshell/signal-block είναι ο πιο δίκαιος και διαισθητικά λογικός συνδυασμός (σειρά FIFO) 53 lalis@inf.uth.gr

Έλεγχος προδιαγραφών Αρκετές γλώσσες και περιβάλλοντα εκτέλεσης υποστηρίζουν μηχανισμούς συγχρονισμού που έχουν πολλές ομοιότητες με τον μηχανισμό του ελεγκτή Πριν αρχίσετε να γράφετε κώδικα, βεβαιωθείτε ότι γνωρίζετε ακριβώς ποιο μοντέλο ελεγκτή υλοποιούν Οι διαφορές ανάμεσα σε eggshell/open σε συνδυασμό με signal-block/signal-continue επηρεάζουν την ορθότητα του κώδικα Αν δεν υπάρχουν ξεκάθαρες προδιαγραφές (πράγμα σύνηθες), ο κώδικας πρέπει να σχεδιαστεί έτσι ώστε να λειτουργεί σωστά για όλους τους συνδυασμούς Στην συνέχεια υποθέτουμε eggshell/signal-block 54 lalis@inf.uth.gr

Ελεγκτές και σχεδίαση λογισμικού 55 lalis@inf.uth.gr

Οι ελεγκτές δεν είναι πανάκεια Όπως κάθε εργαλείο/μηχανισμός συγχρονισμού, χρειάζεται προσοχή για να αποφεύγονται λάθη Πολλές φορές, τα λάθη δεν είναι προφανή Κλασικό πρόβλημα: αδιέξοδα (deadlocks) Ιδίως σε αντικειμενοστραφή περιβάλλοντα (όπου η ροή εκτέλεσης δεν είναι ορατή εκ των προτέρων) Nesting problem: Σύνθεση πολύπλοκων τμημάτων λογισμικού από πιο απλά τμήματα/συστατικά Reentrancy problem: Επαναφορά, με έμμεσο τρόπο, πίσω στο ίδιο πλαίσιο συγχρονισμού 56 lalis@inf.uth.gr

Monitor B Monitor C Monitor A 57 lalis@inf.uth.gr

class Semaphore { private int val; Semaphore(int val) { this.val = val; synchronized public void down() throws InterruptedException { while (val == 0) { wait(); val--; synchronized public void up() { val++; notify(); 58 lalis@inf.uth.gr

class SafeBuffer { Object[] buf; int in, out, n; Semaphore full, empty; SafeBuffer(int size) { in=0; out=0; n=size; buf=new Object[n]; full=new Semaphore(0); empty=new Semaphore(n); synchronized public void put(object o) throws InterruptedException { empty.down(); buf[in]=o; in=(in+1)%n; full.up(); προβληματικό synchronized public Object get() throws InterruptedException { Object o; full.down(); o=buf[out]; out=(out+1)%n; empty.up(); return(o); 59 lalis@inf.uth.gr

class SafeBuffer2 { Object[] buf; int in, out, n; Semaphore full, empty; SafeBuffer2(int size) { in=0; out=0; n=size; buf=new Object[n]; full=new Semaphore(0); empty=new Semaphore(n); public void put(object o) throws InterruptedException { empty.down(); synchronized(this) { buf[in]=o; in=(in+1)%n; full.up(); public Object get() throws InterruptedException { Object o; full.down(); synchronized(this) { o=buf[out]; out=(out+1)%n; empty.up(); return(o); 60 lalis@inf.uth.gr

code Monitor function pointer 61 lalis@inf.uth.gr

private int myval; private Listener[] mylisteners; public synchronized void addlistener(listener l) { public synchronized void rmvlistener(listener l) { public synchronized void setvalue(int val) { myval = val; for (int i = 0; i < mylisteners.length; i++) { mylisteners[i].valuechanged(val); προβληματικό 62 lalis@inf.uth.gr

private int myval; private Listener[] mylisteners; public synchronized void addlistener(listener l) { public synchronized void rmvlistener(listener l) { public void setvalue(int val) { synchronized (this) { myval = val; listeners = mylisteners.clone(); προβληματικό for (int i = 0; i < listeners.length; i++) { listeners[i].valuechanged(val); 63 lalis@inf.uth.gr