Coordination aspect Review of AOP Summary of threads

  • Slides: 43
Download presentation
Coordination aspect • Review of AOP • Summary of threads in Java • COOL

Coordination aspect • Review of AOP • Summary of threads in Java • COOL (COOrdination Language) – Design decisions – Implementation at Xerox PARC 1/12/2022 Synchronization/AOP 1

the goal is a clear separation of concerns we want: – natural decomposition –

the goal is a clear separation of concerns we want: – natural decomposition – concerns to be cleanly localized – handling of them to be explicit – in both design and implementation 1/12/2022 Synchronization/AOP 2

achieving this requires. . . • synergy among – problem structure and – design

achieving this requires. . . • synergy among – problem structure and – design concepts and – language mechanisms “natural design” “the program looks like the design” 1/12/2022 Synchronization/AOP 3

Cross-cutting of components and aspects better program ordinary program structure-shy functionality structure synchronization 1/12/2022

Cross-cutting of components and aspects better program ordinary program structure-shy functionality structure synchronization 1/12/2022 Synchronization/AOP Components Aspect 1 Aspect 2 4

Aspect-Oriented Programming components and aspect descriptions High-level view, implementation may be different Source Code

Aspect-Oriented Programming components and aspect descriptions High-level view, implementation may be different Source Code (tangled code) weaver (compiletime) 1/12/2022 Synchronization/AOP 5

Threads ! Thread 1 1/12/2022 Synchronization/AOP Thread 2 6

Threads ! Thread 1 1/12/2022 Synchronization/AOP Thread 2 6

Coordination aspect • Put coordination code about thread synchronization in one place. • Threads

Coordination aspect • Put coordination code about thread synchronization in one place. • Threads are synchronized through methods. • Method synchronization – Exclusion sets – Method managers 1/12/2022 Synchronization/AOP 7

Java Threads • Thread class in Standard Java libraries • Thread worker = new

Java Threads • Thread class in Standard Java libraries • Thread worker = new Thread(. . . ) • start method spawns a new thread of control based on Thread object. start invokes the threads run method: active thread 1/12/2022 Synchronization/AOP 8

Java Threads • synchronized method: locks object. A thread invoking a synchronized method on

Java Threads • synchronized method: locks object. A thread invoking a synchronized method on the same object must wait until lock released. Mutual exclusion of two threads. class Account { synchronized double get. Balance() { return balance; } synchronized void deposit(double a) { balance += a; } } 1/12/2022 Synchronization/AOP 9

Java Threads • synchronized statements synchronized (expr) statement • lock an object without invoking

Java Threads • synchronized statements synchronized (expr) statement • lock an object without invoking a synchronized method • expr must produce an object to lock 1/12/2022 Synchronization/AOP 10

Java Threads • communication between threads with wait and notify (defined in class Object).

Java Threads • communication between threads with wait and notify (defined in class Object). 1/12/2022 Synchronization/AOP 11

Java Threads • notify: after change of data that some other thread is waiting

Java Threads • notify: after change of data that some other thread is waiting on synchronized void change. Condition(){ // change some value notify. All(); // wakes all waiting threads } 1/12/2022 Synchronization/AOP 12

Problem with synchronization code: it is tangled with component code class Bounded. Buffer {

Problem with synchronization code: it is tangled with component code class Bounded. Buffer { Object[] array; int put. Ptr = 0, take. Ptr = 0; int used. Slots = 0; Bounded. Buffer(int capacity){ array = new Object[capacity]; } 1/12/2022 Synchronization/AOP 13

Tangling synchronized void put(Object o) { while (used. Slots == array. length) { try

Tangling synchronized void put(Object o) { while (used. Slots == array. length) { try { wait(); } catch (Interrupted. Exception e) {}; } array[put. Ptr] = o; put. Ptr = (put. Ptr +1 ) % array. length; if (used. Slots==0) notify. All(); used. Slots++; // if (used. Slots++==0) notify. All(); } 1/12/2022 Synchronization/AOP 14

notify. All if (used. Slots==0) notify. All(); used. Slots++; // if (used. Slots++==0) notify.

notify. All if (used. Slots==0) notify. All(); used. Slots++; // if (used. Slots++==0) notify. All(); • An extra notify. All never hurts correctness (unless you require hard real-time deadlines), but may reduce efficiency 1/12/2022 Synchronization/AOP 15

notify. All if (used. Slots==0) notify. All(); used. Slots++; // if (used. Slots++==0) notify.

notify. All if (used. Slots==0) notify. All(); used. Slots++; // if (used. Slots++==0) notify. All(); • Do we get enough notify? • Need to notify only if buffer was empty and just got a new element 1/12/2022 Synchronization/AOP 16

Solution: tease apart basics and synchronization • write core behavior of buffer • write

Solution: tease apart basics and synchronization • write core behavior of buffer • write coordinator which deals with synchronization • use weaver which combines them together • simpler code • replace synchronized, wait, notify and notify. All by coordinators 1/12/2022 Synchronization/AOP 17

With coordinator: basics Bounded. Buffer { public void put (Object o) (@ array[put. Ptr]

With coordinator: basics Bounded. Buffer { public void put (Object o) (@ array[put. Ptr] = o; put. Ptr = (put. Ptr+1)%array. length; used. Slots++; @) public Object take() (@ Object old = array[take. Ptr]; array[take. Ptr] = null; take. Ptr = (take. Ptr+1)%array. length; used. Slots--; return old; @) 1/12/2022 Synchronization/AOP 18

Coordinator coordinator Bounded. Buffer { selfex put, take; exclusion sets mutex {put, take} condition

Coordinator coordinator Bounded. Buffer { selfex put, take; exclusion sets mutex {put, take} condition empty=true, full=false; coordinator variables 1/12/2022 Synchronization/AOP 19

Coordinator method managers with requires clauses and entry/exit clauses put requires (!full) { on

Coordinator method managers with requires clauses and entry/exit clauses put requires (!full) { on exit {empty=false; if (used. Slots==array. length) full=true; }} take requires (!empty) { on exit {full=false; if (used. Slots==0) empty=true; }} } 1/12/2022 Synchronization/AOP 20

exclusion sets • selfex A. f, B. g; – only one thread can call

exclusion sets • selfex A. f, B. g; – only one thread can call a selfex method – A. f and B. g may run simultaneously. • mutex {g, h, i} mutex {f, k, l} – if a thread calls a method in a mutex set, no other thread may call a method in the same mutex set. 1/12/2022 Synchronization/AOP 21

Multi-class coordination supported coordinator A, B { selfex A. put, B. take; mutex {B.

Multi-class coordination supported coordinator A, B { selfex A. put, B. take; mutex {B. put, A. take} condition empty=true, full=false; . . . 1/12/2022 Synchronization/AOP 22

Design decisions behind COOL • The smallest unit of synchronization is the method. •

Design decisions behind COOL • The smallest unit of synchronization is the method. • The provider of a service defines the synchronization (monitor approach). • Coordination is contained within one coordinator. • Association from object to coordinator is static. 1/12/2022 Synchronization/AOP 23

Design decisions behind COOL • Deals with thread synchronization within each execution space. No

Design decisions behind COOL • Deals with thread synchronization within each execution space. No distributed synchronization. • Coordinators can access the objects’ state, but they can only modify their own state. Synchronization does not “disturb” objects. Currently a design rule not checked by implementation. 1/12/2022 Synchronization/AOP 24

COOL • Provides means for dealing with mutual exclusion of threads, synchronization state, guarded

COOL • Provides means for dealing with mutual exclusion of threads, synchronization state, guarded suspension and notification ! Thread 1 Thread 2 coordinator 1/12/2022 Synchronization/AOP 25

COOL • Identifies “good” abstractions for coordinating the execution of OO programs – coordination,

COOL • Identifies “good” abstractions for coordinating the execution of OO programs – coordination, not modification of the objects – mutual exclusion: sets of methods – preconditions on methods 1/12/2022 Synchronization/AOP 26

plain Java public class Shape { protected double x_ = 0. 0; y_ =

plain Java public class Shape { protected double x_ = 0. 0; y_ = 0. 0; width_ = 0. 0; height_ = 0. 0; double x() { return x_(); } double y() { return y_(); } double width(){ return width_(); } double height(){ return height_(); } COOL Shape coordinator Shape { selfex {adjust. Location, adjust. Dimensions} mutex {adjust. Location, x} mutex {adjust. Location, y} mutex {adjust. Dimensions, width} mutex {adjust. Dimensions, height} } void adjust. Location() { x_ = long. Calculation 1(); y_ = long. Calculation 2(); } void adjust. Dimensions() { width_ = long. Calculation 3(); height_ = long. Calculation 4(); } } 1/12/2022 Synchronization/AOP 27

Extreme cases • All methods synchronized: monitor. A lot of parallelism is excluded. Conservative.

Extreme cases • All methods synchronized: monitor. A lot of parallelism is excluded. Conservative. • No method synchronized: A lot of parallelism. Very dangerous. Bad things can happen. Don’t do it. • Exclusion sets: are in between. 1/12/2022 Synchronization/AOP 28

Programming with COOL Protocol object/coordinator: coordinator 3 7 2 4 6 8 1 5

Programming with COOL Protocol object/coordinator: coordinator 3 7 2 4 6 8 1 5 m() {…} object 1/12/2022 1: method invocation 2: request presented to the coordinator 3: coordinator checks synchronization state, eventually suspending thread; when thread can proceed, coordinator performs “on_entry” actions 4: request proceeds to the object 5: method execution 6: return is presented to coordinator 7: coordinator performs “on_exit” actions Synchronization/AOP 29 8: method returns

COOL View of Classes • Stronger visibility: – coordinator can access: • all methods

COOL View of Classes • Stronger visibility: – coordinator can access: • all methods and variables of its classes, independent of access control • all non-private methods and variables of their superclasses • Limited actions: – only read variables, not modify them – only coordinate methods, not invoke them 1/12/2022 Synchronization/AOP 30

Xerox PARC Implemention Implementing COOL Programming with COOL coordinator object coordinator 3 1 33

Xerox PARC Implemention Implementing COOL Programming with COOL coordinator object coordinator 3 1 33 7 2 4 6 8 5 m() {…} 1 object Implementation Semantics 1/12/2022 7 Synchronization/AOP 31

COOL public class Bounded. Buffer { private Object array[]; private int put. Ptr =

COOL public class Bounded. Buffer { private Object array[]; private int put. Ptr = 0, take. Ptr = 0; private int used. Slots = 0; public Bounded. Buffer(int capcty){ array = new Object[capcty]; } public void put(Object o) { array[put. Ptr] = o; put. Ptr = (put. Ptr+1)%array. length; used. Slots++; } public Object take() { Object old = array[take. Ptr]; array[take. Ptr] = null; take. Ptr = (take. Ptr+1)%array. length; used. Slots--; return old; } } 1/12/2022 coordinator Bounded. Buffer { selfex {put, take} mutex {put, take}; boolean full=(@ false @), empty=(@ true @); put requires (@ !full @) { on exit (@ empty = false; if (used. Slots==array. length) full = true; @) } take requires (!empty){ on exit (@ full = false; if (used. Slots == 0) empty = true; @) } } Synchronization/AOP 32

Implementing COOL Bounded. Buffer. Coord _dcoord // rest of the variables protected void _d_put(Object

Implementing COOL Bounded. Buffer. Coord _dcoord // rest of the variables protected void _d_put(Object o){ //implementation code 2 } 5 public void put(Object o) { _dcoord. enter_put(this); try { _d_put(o); } 6 1 finally { _dcoord. exit_put(this); } } protected Object _d_take() { //implementation code } public Object take() { //similar to put } 1/12/2022 4 8 // variable next page synchronized void enter_put(Bounded. Buffer o){ //. . . 3 } synchronized void exit_put(Bounded. Buffer o) { //. . . 7 } synchronized void enter_take(Bounded. Buffer o){ //. . . } synchronized void exit_take(Bounded. Buffer o) { //. . . } Synchronization/AOP 33

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State();

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State take = new Meth. State(); boolean empty = true, full = false; public synchronized void enter_put(Bounded. Buffer o) { while (put. is. Busy. By. Other. Thread() || take. is. Busy. By. Other. Thread() || full) { try { wait(); } catch (Interrupted. Exception e) {} } put. in(); } public synchronized void exit_put(Bounded. Buffer o) { put. out(); empty = false; if (o. _dget_usedlots()==o. _dget_size()) full=true; notify. All(); }. . . 1/12/2022 Synchronization/AOP 34

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State();

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State take = new Meth. State(); boolean empty = true, full = false; to keep track of method execution state public synchronized void enter_put(Bounded. Buffer o) { while (put. is. Busy. By. Other. Thread() || take. is. Busy. By. Other. Thread() || full) { try { wait(); } catch (Interrupted. Exception e) {} } put. in(); } public synchronized void exit_put(Bounded. Buffer o) { put. out(); empty = false; if (o. _dget_usedlots() == o. _dget_size()) full = true; notify. All(); } 1/12/2022 Synchronization/AOP 35. . .

One class to support COOL class Method. State { int depth = 0; Vector

One class to support COOL class Method. State { int depth = 0; Vector t 1 = new Vector(); final public boolean is. Busy. By. Other() { if (depth > 0 && !t 1. contains(Thread. current. Thread())) return true; else return false; } final public void in() { depth++; t 1. add. Element(Thread. current. Thread()); } final public void out() { depth--; …} 1/12/2022 Synchronization/AOP 36

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State();

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State take = new Meth. State(); boolean empty = true, full = false; coordination vars public synchronized void enter_put(Bounded. Buffer o) { while (put. is. Busy. By. Other. Thread() || take. is. Busy. By. Other. Thread() || full) { try { wait(); } catch (Interrupted. Exception e) {} } put. in(); } public synchronized void exit_put(Bounded. Buffer o) { put. out(); empty = false; if (o. _dget_usedlots()==o. _dget_size()) full=true; notify. All(); }. . . 1/12/2022 Synchronization/AOP 37

class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State

class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State take = new Meth. State(); boolean empty = true, full = false; Implementing COOL public synchronized void enter_put(Bounded. Buffer o) { while (put. is. Busy. By. Other. Thread() || take. is. Busy. By. Other. Thread() || full) { try { wait(); } catch (Interrupted. Exception e) {} conditions for waiting } put. in(); } public synchronized void exit_put(Bounded. Buffer o) { put. out(); empty = false; if (o. _dget_usedlots() == o. _dget_size()) full = true; notify. All(); }. . . 1/12/2022 Synchronization/AOP 38

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State();

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State take = new Meth. State(); boolean empty = true, full = false; public synchronized void enter_put(Bounded. Buffer o) { while (put. is. Busy. By. Other. Thread() || take. is. Busy. By. Other. Thread() || full) { try { wait(); } catch (Interrupted. Exception e) {} } put. in(); update method state } public synchronized void exit_put(Bounded. Buffer o) { put. out(); empty = false; if (o. _dget_usedlots() == o. _dget_size()) full = true; notify. All(); }. . . 1/12/2022 Synchronization/AOP 39

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State();

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State take = new Meth. State(); boolean empty = true, full = false; public synchronized void enter_put(Bounded. Buffer o) { while (put. is. Busy. By. Other. Thread() || take. is. Busy. By. Other. Thread() || full) { try { wait(); } catch (Interrupted. Exception e) {} } put. in(); } public synchronized void exit_put(Bounded. Buffer o) { put. out(); empty = false; update method state if (o. _dget_usedlots() == o. _dget_size()) full = true; notify. All(); }. . . 1/12/2022 Synchronization/AOP 40

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State();

Implementing COOL class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State take = new Meth. State(); boolean empty = true, full = false; public synchronized void enter_put(Bounded. Buffer o) { while (put. is. Busy. By. Other. Thread() || take. is. Busy. By. Other. Thread() || full) { try { wait(); } catch (Interrupted. Exception e) {} } put. in(); } public synchronized void exit_put(Bounded. Buffer o) { put. out(); on_exit statements empty = false; if (o. _dget_usedlots()==o. _dget_size()) full=true; notify. All(); } 1/12/2022 Synchronization/AOP 41. . .

class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State

class Bounded. Buffer. Coord { Meth. State put = new Meth. State(); Meth. State take = new Meth. State(); boolean empty = true, full = false; Implementing COOL public synchronized void enter_put(Bounded. Buffer o) { while (put. is. Busy. By. Other. Thread() || take. is. Busy. By. Other. Thread() || full) { try { wait(); } catch (Interrupted. Exception e) {} } put. in(); } public synchronized void exit_put(Bounded. Buffer o) { put. out(); empty = false; if (o. _dget_usedlots()==o. _dget_size()) full=true; notify. All(); notify state change }. . . 1/12/2022 Synchronization/AOP 42

Acknowledgments • Many of the viewgraphs prepared by Crista Lopes for her Ph. D.

Acknowledgments • Many of the viewgraphs prepared by Crista Lopes for her Ph. D. work supported by Xerox PARC. • Implementation of COOL for Demeter/Java by Josh Marshall. Integration into Demeter/Java with Doug Orleans. • ECOOP ‘ 94 paper on synchronization patterns by Lopes/Lieberherr. 1/12/2022 Synchronization/AOP 43