Presentation is loading. Please wait.

Presentation is loading. Please wait.

Safe Concurrent Programming In Java with CSP Taken from a presentation by Chris Nevison Colgate University.

Similar presentations


Presentation on theme: "Safe Concurrent Programming In Java with CSP Taken from a presentation by Chris Nevison Colgate University."— Presentation transcript:

1 Safe Concurrent Programming In Java with CSP Taken from a presentation by Chris Nevison Colgate University

2 Overview  Why Concurrent Programming  Concurrent Threads in Java  Java Monitors  Concurrent Sequential Processes (CSP)  CSP in Java  Examples of Concurrent Programs using CSP  Data Flow using CSP  The Future ?

3 Why Concurrent Programming?  Sequential programming is artificial –Most real world situations occur concurrently –Question should be “why sequential programming?”  Many programs are more naturally constructed as concurrent programs  Multiple processors, client-server interactions are concurrent  Parallel computing for performance

4 Concurrent Threads in Java  Extend class Thread or  Implement interface Runnable -- Preferred!  start member functions starts thread, runs member function run  Memory is shared -- threads communicate by reading/writing to same memory locations  Need Synchronization to avoid race conditions  Threads run concurrently – time-sliced on a single processor –in parallel on an SMP (depending on OS)

5 Thread States  New -- declared, not yet started  Runnable -- ready to run  Running -- currently running  Blocked –blocked on I/O, wait on Monitor, sleep, join  Suspended -- by call to suspend  Suspended-Blocked -- suspend called while blocked  Dead -- run ends, stop called

6 Thread States NewRunnable Running Blocked start stop run ends scheduled descheduled yield wait sleep join I/O notify / notifyall sleep expires I/O completes join completes self control scheduler external control Dead

7 Example Problem: “unidirectional TSP” (Hartley) Given a matrix of costs, a path through the matrix is a sequence of cells in the matrix, such that the cell on the path in column k+1 is in the same or a neighboring row to the cell on the path in column k (where the first and last row wrap around). The unidirectional TSP is the problem of finding the least cost path from the first to the last column in the matrix.

8 Example Problem: “unidirectional TSP” (Hartley) 12 5 9 6 1011 6 4 9 8 5 8 7 9 8 3 Least Cost Path

9 Example Problem: “unidirectional TSP” (Hartley) 1259 6 10116 4 985 8 798 3 6 4 8 3 12 10 8 11 15 19 16 17 27 25 22

10 unidirectional TSP parallel control 1259 6 10116 4 987 8 798 3 Proc 0 Proc 1 Proc 2 Proc 3

11 class TSPRowSolver extends MyObject implements Runnable{ private int myRow = 0; private Matrix costMat = null; private Matrix totMat = null; private Matrix dirMat = null; private Thread t = null; public TSPRowSolver(int row, Matrix cost, Matrix tot, Matrix dir){ myRow = row; costMat = cost; totMat = tot; dirMat = dir; t = new Thread(this); t.start(); }

12 public void run(){ // initialize values int col = numC - 1; totMat.setVal(myRow, col, costMat.val(myRow, col));

13 for(col = col - 1; col >= 0; col--){ up = (myRow - 1 + numR) % numR; dn = (myRow + 1) % numR; upVal = totMat.val(up, col+1); rowVal = totMat.val(myRow, col+1); dnVal = totMat.val(dn, col+1); if((upVal < rowVal) && (upVal < dnVal)){ totMat.setVal(myRow, col, upVal + costMat.val(myRow,col)); dirMat.setVal(myRow, col, up); } else if(dnVal < rowVal && dnVal <= upVal){ // set totMat and dirMat} else{// rowVal is largest,set totMat,dirMat } }

14 unidirectional TSP No Control -- Race Condition 1259 6 10116 4 985 8 798 3 0 0 0 0 0 0 0 0 0 0 0 6 4 8 3 8 0 8 1011 12 1519 17 271718 15

15 Monitors in Java  Key word synchronized  Only one thread can “possess” monitor at a time  When conditions are not ready Thread can wait –thread blocks –Another thread calls notify or notifyall »On notify one waiting process becomes runnable »On notifyall all waiting processes become runnable

16 Example: Barrier Synchronization  A set of concurrent threads are included in the barrier  Each included thread checks the barrier at the synchronization point  No thread can pass the synchronization point until all threads in the barrier have reached it.

17 class Barrier{ private int releaseNum; private int count; Barrier(int num){ releaseNum = num; count = 0; } public synchronized void check(){ count++; if(count < releaseNum){ try { wait();} catch(InterruptedException e){} } else{ count = 0; notifyAll(); } } }

18 class TSPRowSolver extends MyObject implements Runnable{ // other declarations and constructor public void run(){ // initialization totMat.setVal(myRow, col, costMat.val(myRow, col)); for(col = col - 1; col >= 0; col--){ bar1.check(); // includes all rows // computation } bar2.check(); // includes all rows and main }

19 Alternate Solution  Synchronize each row to its neighbors  Needs a monitor for each row  Potentially more efficient –lets rows run further before blocking

20 Classic Problem: Producer-Consumers with Buffer  Buffer accessed by both producer and consumers –critical section for update of contents of buffer –consumer must wait if buffer is empty  Use monitor to control access to buffer –Following uses adaptation of buffer (cubbyhole) solution given in Sun documentation

21 “Wot, No Chickens!”  Peter Welch, University of Kent  Five Philosophers (consumers) –Think –Go to Canteen to get Chicken for dinner –Repeat  Chef (producer) –produces four chickens at a time and delivers to canteen

22 “Wot, No Chickens!”  Philosopher 0 is greedy -- never thinks  Other philosophers think 3 time units before going to eat  Chef takes 2 time units to cook four chickens  Chef takes 3 time units to deliver chickens –occupies canteen while delivering  Simplified code follows -- leaves out exception handling try-catch

23 class Canteen { private int n_chickens = 0; public synchronized int get(int id) { while (n_chickens == 0) { wait(); // Wot, No Chickens! } n_chickens--;// Those look good...one please return 1; } public synchronized void put(int value) { Thread.sleep(3000); // delivering chickens.. n_chickens += value; notifyAll (); // Chickens ready! }

24 class Chef extends Thread { private Canteen canteen; public Chef (Canteen canteen) { this.canteen = canteen; start (); } public void run () { int n_chickens; while (true) { sleep (2000);// Cooking... n_chickens = 4; canteen.put (n_chickens); }

25 class Phil extends Thread { private int id; private Canteen canteen; public Phil(int id, Canteen canteen) { this.id = id; this.canteen = canteen; start (); } public void run() { int chicken; while (true) { if (id > 0) { sleep(3000); // Thinking... } chicken = canteen.get(id);// Gotta eat... } // mmm...That's good }

26 class College { public static void main (String argv[]) { int n_philosophers = 5; Canteen canteen = new Canteen (); Chef chef = new Chef (canteen); Phil[] phil = new Phil[n_philosophers]; for (int i = 0; i < n_philosophers; i++) { phil[i] = new Phil (i, canteen); }

27 “Wot, No Chickens!” Canteen P0P1P2P3P4 LibraryWaiting Outside Wait Inside Chef Cooking PickupDelivery

28 “Wot, No Chickens!” Canteen P0P1P2P3P4 LibraryWaiting Outside Wait Inside Chef Cooking PickupDelivery P1P2P3P4 Chef P0

29 P4P3P1P2P1 “Wot, No Chickens!” Canteen LibraryWaiting Outside Wait Inside P1 P2 P3 P4 P0 Cooking PickupDelivery Chef Wot No Chickens!

30 Problems with Java Monitors  Semantics of Notify / NotifyAll ???  Breaks O-O model –Threads are controlled by calling functions inside monitor –Depend on notification by other threads –Multiple monitors can easily lead to deadlock –Monitors can easily lead to starvation –Global ! knowledge needed to adequately coordinate multiple monitors

31 Communicating Sequential Processes  CSP Anthony Hoare, 1978  Processes (concurrent threads) –run sequential code –communicate process-to-process via channels  Channels are point-to-point and synchronous (unbuffered) –standard is one-to-one, but many-to-one, one-to- many, and many-to-many have been implemented –Buffering can easily be added.

32 Communicating Sequential Processes  Control –Sequential (default, can also be explicit) –Parallel »a set of processes run to completion to complete a parallel construct –Alternative »allows selection of first channel ready to communicate »theoretically any communication could be included, in practice only reads from channels

33 Occam 2  Language designed specifically for parallel computing using the CSP model  Implemented on the Transputer, a chip designed for efficient on-chip (time-sliced) concurrency and communications with other transputers via channels  Proves efficacy of CSP model

34 Java with CSP (JCSP) (University of Kent)  A library of CSP constructs –Written in pure Java –Provides CSP tools easy to use in Java –Hides difficult Monitor synchronization  Utilities –Common modular JCSP constructs –facilitates Data-Flow style of programming  JCSP AWT –extends Java AWT to use JCSP Channels

35 A (c) || B (c) c A A B B Synchronised Communication B may read from c at any time, but has to wait for a write. c ? x A may write on c at any time, but has to wait for a read. c ! 42

36 A (c) || B (c) c A A B B Synchronised Communication c ? x Only when both A and B are ready can the communication proceed over the channel c. c ! 42

37 ‘Legoland’ Catalog IdInt (in, out) in out IdInt SuccInt (in, out) inout SuccInt PlusInt (in0, in1, out) in1 out in0 + + PrefixInt (n, in, out) out in n n TailInt (in, out) inout TailInt Delta2Int (in, out0, out1) out1 out0 in

38 ‘Legoland’ Catalog _ This is a catalog of fine-grained processes - think of them as pieces of hardware (e.g. chips). They process data ( int s) flowing through them. _ They are presented not because we suggest working at such fine levels of granularity … _ They are presented in order to build up fluency in working with parallel logic.

39 out in IdInt IdInt (in, out) = in?x --> out!x --> IdInt (in, out) SuccInt in out SuccInt (in, out) = in?x --> out!(x + 1) --> SuccInt (in, out) in1 out in0 + + PlusInt (in0, in1) = (in0?x0 --> SKIP || inl?x1 --> SKIP); out!(x0 + x1) --> PlusInt (in0, in1, out) Note the parallel input

40 Delta2Int (in, out0, out1) = in?x --> (out0!x --> SKIP || out1!x --> SKIP); Delta2Int (in, out0, out1) out1 out0 in out in n n PrefixInt (n, in, out) = out!n --> IdInt (in, out) TailInt (in, out) = in?x --> IdInt (in, out) inout TailInt Note the parallel output

41 A Blocking FIFO Buffer Fifo (n, in, out) = IdInt (in, c[0]) || ([||i = 0 FOR n-2] IdInt (c[i], c[i+1])) || IdInt (c[n-2], out) out in IdInt c[0]c[1] c[n-2] Fifo (n) Note: this is such a common idiom that it is provided as a (channel) primitive in JCSP.

42 Prefix(1)Prefix(0) Delta Tail Plus Fibonacci

43 Java with CSP (JCSP) (University of Kent)  A library of CSP constructs –Written in pure Java –Provides CSP tools easy to use in Java –Hides difficult Monitor synchronization  Utilities –Common modular JCSP constructs –facilitates Data-Flow style of programming  JCSP AWT –extends Java AWT to use JCSP Channels

44 JCSP constructs CSProcess Interface, comparable to Runnable must implement run() function Channels Various types. As parameters can specify read only ( ChannelInput ) or write-only ( ChannelOutput ) functions read() and write(object) Declared and passed as parameters to CSProcess class constructors Parallel A CSProcess which takes an array of other CSProcesses and runs them in parallel, terminates when all constituent processes complete run.

45 class Identity implements CSProcess{ ChannelInputInt in; ChannelOutputInt out; public Identity(ChannelInputInt in, ChannelOutputInt out){ this.in = in; this.out = out; } public void run(){ while(true){ int item = in.read(); out.write(item); }

46 class Prefix implements CSProcess{ ChannelInputInt in; ChannelOutputInt out; int first; public Prefix(int first, ChannelInputInt in, ChannelOutputInt out){ this.in = in; this.out = out; this.first = first; } public void run(){ out.write(first); new Identity(in, out).run(); }

47 class Tail implements CSProcess{ ChannelInputInt in; ChannelOutputInt out; public Tail(ChannelInputInt in, ChannelOutputInt out){ this.in = in; this.out = out; } public void run(){ in.read(); new Identity(in, out).run(); }

48 class Plus implements CSProcess{ ChannelInputInt in1; ChannelInputInt in2; ChannelOutputInt out; ProcessReadInt r1; ProcessReadInt r2; public Plus(ChannelInputInt in1, ChannelInputInt in2, ChannelOutputInt out){ this.in1 = in1; this.in2 = in2; this.out = out; r1 = new ProcessReadInt(in1); r2 = new ProcessReadInt(in2); } public void run(){ while(true){ new Parallel( new CSProcess[]{r1, r2}).run(); out.write(r1.value + r2.value); } } }

49 class Delta implements CSProcess{ ChannelInputInt in; ChannelOutputInt out1; ChannelOutputInt out2; public Delta(ChannelInputInt in, ChannelOutputInt out1, ChannelOutputInt out2){ this.in = in; this.out1 = out1; this.out2 = out2; } public void run(){ while(true){ int item = in.read(); new Parallel( new CSProcess[]{ new ProcWriteInt(out1, item), new ProcWriteInt(out2, item) }).run(); } } }

50 Prefix(1)Prefix(0) Delta Tail Plus Fibonacci

51 class Fibonacci implements CSProcess{ ChannelOutputInt out; public Fibonacci(ChannelOutputInt out){ this.out = out; } public void run(){ One2OneChannelInt P1toP0 = new One2OneChannelInt; One2OneChannelInt P0toD0 = new One2OneChannelInt; One2OneChannelInt D0toD1 = new One2OneChannelInt; One2OneChannelInt D0toT = new One2OneChannelInt; One2OneChannelInt TtoPlus = new One2OneChannelInt; One2OneChannelInt D1toPlus = new One2OneChannelInt; One2OneChannelInt PlustoP1 = new One2OneChannelInt; new Parallel( CSProcess[]{ Prefix(1, PlustoP1, P1toP0), Prefix(0, P1toP0, P1toD0), Delta(P1toD0, D0toD1, D0toT), Delta(D0toD1, out, D1toPlus), Tail(D0toT, TtoPlus), Plus(TtoPlus, D1toPlus, PlustoP1) }).run(); }

52 Unidirectional TSP Using JCSP Circuit RowSolver 0RowSolver 1RowSolver 2RowSolver 3 MasterMaster Up Down MasterToRow RowToMaster

53 class tspcircuit implements CSProcess{ private Matrix costmat; public tspcircuit(Matrix costmat){ this.costmat = costmat; } public void run(){ int numR = costmat.numRows(); One2OneChannel MastertoRow[] = new One2OneChannel[numR]; One2OneChannel RowtoMaster[] = new One2OneChannel[numR]; One2OneChannel Up[] = new One2OneChannel[numR]; One2OneChannel Down[] = new One2OneChannel[numR]; for(int r = 0; r < numR; r++){ MastertoRow[r] = new One2OneChannel(); RowtoMaster[r] = new One2OneChannel(); Up[r] = new One2OneChannel(); Down[r] = new One2OneChannel(); }

54 TSPRowSolver rowsolvers[] = new TSPRowSolver[numR]; for(int r = 0; r < numR; r++) rowsolvers[r] = new TSPRowSolver (r, MastertoRow[r], Down[r], Up[(r + 1) % numR], RowtoMaster[r], Up[r], Down[(r + 1) % numR]); new Parallel(new CSProcess[]{ new tspMaster(costmat, MastertoRow, RowtoMaster), new Parallel(rowsolvers) }).run(); }}

55 class TSPRowSolver extends MyObject implements CSProcess{ private ChannelInput fromMaster; private ProcessRead readAbove = null; private ProcessRead readBelow = null; private ChannelOutput toMaster; private ChannelOutput toAbove; private ChannelOutput toBelow; private int myRow; public TSPRowSolver(int row, ChannelInput fromMaster, ChannelInput fromAbove, ChannelInput fromBelow, ChannelOutput toMaster, ChannelOutput toAbove, ChannelOutput toBelow){ myRow = row; this.fromMaster = fromMaster; readAbove = new ProcessRead(fromAbove); readBelow = new ProcessRead(fromBelow); this.toMaster = toMaster; this.toAbove = toAbove; this.toBelow = toBelow; }

56 public void run(){ int costrow[] = null; costrow = (int[]) fromMaster.read(); int totrow[] = new int[costrow.length]; int dirrow[] = new int[costrow.length]; int numC = costrow.length; int upVal, dnVal,rowVal; int col = numC - 1; totrow[col] = costrow[col]; dirrow[col] = 0;

57 for(col = col - 1; col >= 0; col--){ rowVal = costrow[col+1]; new Parallel(new CSProcess[]{ new ProcWrite(toAbove, new Integer(totrow[col+1])), new ProcWrite(toBelow, new Integer(totrow[col+1])), readAbove, readBelow }).run(); rowVal = totrow[col+1]; upVal = ((Integer)readAbove.value).intValue(); dnVal = ((Integer)readBelow.value).intValue(); // computation for one entry } System.out.println("Rowsolver " + myRow + " done."); toMaster.write(totrow); toMaster.write(dirrow); }

58 class tspMaster extends MyObject implements CSProcess{ private ProcessWrite writetoRow[] = null; private ProcessRead readfromRow[] = null; private Matrix costmat = null; private Matrix totmat = null; private Matrix dirmat = null; private int numR; public tspMaster(Matrix costmat, ChannelOutput[] toRow, ChannelInput[] fromRow){ this.costmat = costmat; numR = costmat.numRows(); writetoRow = new ProcessWrite[numR]; readfromRow = new ProcessRead[numR]; for(int r = 0; r < numR; r++){ writetoRow[r] = new ProcessWrite(toRow[r]); readfromRow[r] = new ProcessRead(fromRow[r]); }

59 public void run(){ totmat = new Matrix(numR, costmat.numCols()); dirmat = new Matrix(numR, costmat.numCols()); for(int r = 0; r < numR; r++) writetoRow[r].value = costmat.row(r); new Parallel(writetoRow).run(); new Parallel(readfromRow).run(); for(int r = 0; r < numR; r++) totmat.setRow(r, (int[])readfromRow[r].value); new Parallel(readfromRow).run(); for(int r = 0; r < numR; r++) dirmat.setRow(r, (int[])readfromRow[r].value); // Print out results }

60 JCSP Selection  Selects a channel ready for reading from an array of channels  Implies non-determinism  Declare an Alternative object –select function returns index of ready channel –variations allow »boolean array, channel can be selected only if boolean is true »timer -- select continues after specified time »skip -- select continues immediately if no channel is ready

61 “Wot, No Chickens!” Canteen P0P1P2P3P4 Library Chef Cooking ALTALT ALT

62 “Wot, No Chickens!” Canteen P0P1P2P3P4 Library Chef Cooking ALTALT ALT

63 “Wot, No Chickens!” Canteen P0P1P2P3P4 Library Chef Cooking ALTALT ALT

64 “Wot, No Chickens!” Canteen P0P1P2P3P4 Library Chef Cooking ALTALT ALT

65 “Wot, No Chickens!” Canteen P0P1P2P3P4 Library Chef Cooking ALTALT ALT

66 “Wot, No Chickens!” Canteen P0P1P2P3P4 Library Chef Cooking ALTALT ALT

67 “Wot, No Chickens!” Canteen P0P1P2P3P4 Library Chef Cooking ALTALT ALT

68 class Server implements CSProcess{ private AltingChannelInputInt in[] = null; private ChannelOutputInt out[] = null; private ChannelOutputInt toService = null; private ChannelInputInt fromService = null; public Server(AltingChannelInputInt in[], ChannelOutputInt out[], ChannelOutputInt toService, ChannelInputInt fromService){ this.in = in; this.out = out; this.toService = toService; this.fromService = fromService; }

69 public void run(){ // Server Alternative alt = new Alternative(in); int index; while(true){ index = alt.fairSelect(); in[index].read(); toService.write(0); fromService.read(); out[index].write(1); }

70 class Service extends MyObject implements CSProcess{ private AltingChannelInputInt in[] = new AltingChannelInputInt[2]; private ChannelOutputInt toServer; public Service(AltingChannelInputInt fromChef, AltingChannelInputInt fromServer, ChannelOutputInt toServer){ this.in[0] = fromChef; this.in[1] = fromServer; this.toServer = toServer; }

71 public void run(){ // Service int numChicks = 0; int index; boolean ready[] = new boolean[2]; Alternative alt = new Alternative(in); ready[0] = true; while(true){ ready[1] = (numChicks > 0); index = alt.select(ready); if(index == 0){ numChicks += in[0].read(); nap(3000); in[0].read(); } else{ in[1].read(); numChicks--; toServer.write(1); } }

72 class Canteen extends MyObject implements CSProcess{ private AltingChannelInputInt fromPhil[] = null; private ChannelOutputInt toPhil[] = null; private AltingChannelInputInt fromChef = null; public Canteen(AltingChannelInputInt fromPhil[], ChannelOutputInt toPhil[], AltingChannelInputInt fromChef){ this.fromPhil = fromPhil; this.toPhil = toPhil; this.fromChef = fromChef; }

73 public void run(){ // Canteen One2OneChannelInt ServertoService = new One2OneChannelInt(); One2OneChannelInt ServicetoServer = new One2OneChannelInt(); new Parallel( new CSProcess[]{ new Server(fromPhil, toPhil, ServertoService, ServicetoServer), new Service(fromChef, ServertoService, ServicetoServer) }).run(); }

74 class Chef extends MyObject implements CSProcess{ private ChannelOutputInt toCanteen = null; public Chef(ChannelOutputInt toCanteen){ this.toCanteen = toCanteen; } public void run(){ int numChicks = 4; while(true){ nap(2000); // Cooking toCanteen.write(numChicks);// Delivering toCanteen.write(0); // 4 chickens up }

75 class Phil extends MyObject implements CSProcess{ private int id; private ChannelOutputInt toCanteen = null; private ChannelInputInt fromCanteen = null; public Phil (int id, ChannelOutputInt toCanteen, ChannelInputInt fromCanteen) { this.id = id; this.toCanteen = toCanteen; this.fromCanteen = fromCanteen; }

76 public void run () { // Phil int chicken; while (true) { if (id > 0) { nap(3000); // Thinking } toCanteen.write(id); // Gotta Eat chicken = fromCanteen.read();// Mmmm... } // that's good }

77 class CollegeCircuit implements CSProcess{ public void run(){ One2OneChannelInt PhiltoCanteen[] = new One2OneChannelInt[5]; One2OneChannelInt CanteentoPhil[] = new One2OneChannelInt[5]; One2OneChannelInt CheftoCanteen = new ONe2OneChannelInt; Phil phillist[] = new Phil[5]; for(int k = 0; k < 5; k++){ PhiltoCanteen[k] = new One2OneChannelInt(); CanteentoPhil[k] = new One2OneChannelInt(); } for(int k = 0; k < 5; k++) phillist[k] = new Phil(k, PhiltoCanteen[k], CanteentoPhil[k]); new Parallel( new CSProcess[]{ new Parallel(phillist), new Chef(CheftoCanteen), new Canteen(PhiltoCanteen, CanteentoPhil, CheftoCanteen) }).run(); }

78 CSP, Theory  Processes  Events (Communications) –read from channel –write to channel  Rules of Composition –Parallel –Choice –Non-deterministic Selection

79 CSP  Provides an algebraic structure for analysis –a process algebra  Enables us to reason about concurrent systems –prove that a system is deadlock-free –define a denotational semantics for CSP  Tools for automated analysis are available –FDR (Failures/Divergences Refinement)


Download ppt "Safe Concurrent Programming In Java with CSP Taken from a presentation by Chris Nevison Colgate University."

Similar presentations


Ads by Google