+ All Categories
Home > Documents > CSC 543 Multiprocessing & Concurrent Programming, Spring...

CSC 543 Multiprocessing & Concurrent Programming, Spring...

Date post: 10-Mar-2020
Category:
Upload: others
View: 5 times
Download: 0 times
Share this document with a friend
15
page 1 CSC 543 Multiprocessing & Concurrent Programming, Spring 2015 Dr. Dale E. Parson, Assignments 3&4, Debugging, Managing the shutdown process Assignment 3, managing the shutdown process, debugging aids, due by end of Fri. March 27. Assignment 4, minimizing latency for multiple TCP clients, due by end of Sat. April 11. THIS HANDOUT COVERS ONLY ASSIGNMENT 3. ASSIGNMENT 4 WILL COME LATER. This is a three-part assignment. The first two parts are due via gmake turnitin by 11:59 PM on Friday March 27, and the last (and biggest) part is due by 11:59 PM on Saturday April 11. You will need to get your assignment 3 portions working correctly before tackling assignment 4. This document covers only assignment 3. Perform the following steps to get my handout from harry or hermione. As in assignment 1, the reference platform for testing is harry, because its architecture and relatively slow per-CPU speed act as magnifiers in showing the benefits of multiprocessing. Testing during development runs faster on hermione, dumbledore or luna. cd $HOME/multip cp ~parson/multip/spring2015/wordca3.problem.zip wordca3.problem.zip unzip wordca3.problem.zip cd ./wordca3 gmake test1 My handout code supports multiple clients that can send add commands as in assignment 2 (e.g., a0,0,d,ABC), or send run commands as in assignment 2 (e.g., r100000st or r5se), and receive and display the results. The WordCAMTM.main thread 1 is the only client in gmake test1. This test takes just over a minute to run on hermione in the handout code and in my final solution to assignments 3 and 4. Consult files hermione.txt and harry.txt to see the time statistics for the tests on these machines. You can also run gmake test2 using the handout code. In test2 the main thread issues the same set of commands as used in assignment two 2 , but it also issues a second r100000st command concurrently via a client-side socket connection. The main thread sends r100000st to the CA via direct method call as in assignment 2, and then it immediately sends the same r100000st through a TCP/IP socket, thereby emulating a remote client that is issuing commands and observing results across a network. In the handout code the WordCAMTM.Server thread processes each command in series, and so this test almost doubles the run time 3 , and it roughly doubles the generation number of the CA to a value just over 200,000 by the end of test2. Your assignment 4 requires rewriting portions of class Server to schedule run commands from multiple clients concurrently. In assignment 4’s solution, issuing two roughly concurrent r100000st commands at almost the same time – it is impossible to issue them simultaneously, since the Server thread dequeues only 1 command at a time – leads to a test2 run time that is a little longer than the single- client test1, with a generation number just over 100,000 at the end. It is a few greater than test1 because second client command arrives via a socket after the main thread’s direct call to interpret() with r100000st has already advanced the CA by a few states. See the sequence diagram on the next page. 1 WordCAMTM is my highestthroughput solution to assignment 2. 2 See testProject3.txt in the project directory 3 There is process setup and teardown time that does not double, so the full execution time does not double.
Transcript
Page 1: CSC 543 Multiprocessing & Concurrent Programming, Spring 2015faculty.kutztown.edu/parson/spring2015/csc543spring2015... · 2015-03-14 · CSC 543 Multiprocessing & Concurrent Programming,

page 1

CSC 543 Multiprocessing & Concurrent Programming, Spring 2015 Dr. Dale E. Parson, Assignments 3&4, Debugging, Managing the shutdown process Assignment 3, managing the shutdown process, debugging aids, due by end of Fri. March 27. Assignment 4, minimizing latency for multiple TCP clients, due by end of Sat. April 11. THIS HANDOUT COVERS ONLY ASSIGNMENT 3. ASSIGNMENT 4 WILL COME LATER. This is a three-part assignment. The first two parts are due via gmake turnitin by 11:59 PM on Friday March 27, and the last (and biggest) part is due by 11:59 PM on Saturday April 11. You will need to get your assignment 3 portions working correctly before tackling assignment 4. This document covers only assignment 3. Perform the following steps to get my handout from harry or hermione. As in assignment 1, the reference platform for testing is harry, because its architecture and relatively slow per-CPU speed act as magnifiers in showing the benefits of multiprocessing. Testing during development runs faster on hermione, dumbledore or luna.

cd $HOME/multip cp ~parson/multip/spring2015/wordca3.problem.zip wordca3.problem.zip unzip wordca3.problem.zip cd ./wordca3 gmake test1 My handout code supports multiple clients that can send add commands as in assignment 2 (e.g., a0,0,d,ABC), or send run commands as in assignment 2 (e.g., r100000st or r5se), and receive and display the results. The WordCAMTM.main thread1 is the only client in gmake test1. This test takes just over a minute to run on hermione in the handout code and in my final solution to assignments 3 and 4. Consult files hermione.txt and harry.txt to see the time statistics for the tests on these machines. You can also run gmake test2 using the handout code. In test2 the main thread issues the same set of commands as used in assignment two2, but it also issues a second r100000st command concurrently via a client-side socket connection. The main thread sends r100000st to the CA via direct method call as in assignment 2, and then it immediately sends the same r100000st through a TCP/IP socket, thereby emulating a remote client that is issuing commands and observing results across a network. In the handout code the WordCAMTM.Server thread processes each command in series, and so this test almost doubles the run time3, and it roughly doubles the generation number of the CA to a value just over 200,000 by the end of test2. Your assignment 4 requires rewriting portions of class Server to schedule run commands from multiple clients concurrently. In assignment 4’s solution, issuing two roughly concurrent r100000st commands at almost the same time – it is impossible to issue them simultaneously, since the Server thread dequeues only 1 command at a time – leads to a test2 run time that is a little longer than the single-client test1, with a generation number just over 100,000 at the end. It is a few greater than test1 because second client command arrives via a socket after the main thread’s direct call to interpret() with r100000st has already advanced the CA by a few states. See the sequence diagram on the next page.

                                                                                                                         1  WordCAMTM  is  my  highest-­‐throughput  solution  to  assignment  2.  2  See  testProject3.txt  in  the  project  directory  3  There  is  process  setup  and  teardown  time  that  does  not  double,  so  the  full  execution  time  does  not  double.  

Page 2: CSC 543 Multiprocessing & Concurrent Programming, Spring 2015faculty.kutztown.edu/parson/spring2015/csc543spring2015... · 2015-03-14 · CSC 543 Multiprocessing & Concurrent Programming,

page 2

Page 3: CSC 543 Multiprocessing & Concurrent Programming, Spring 2015faculty.kutztown.edu/parson/spring2015/csc543spring2015... · 2015-03-14 · CSC 543 Multiprocessing & Concurrent Programming,

page 3

There are also gmake test3 and gmake test4, which repeat the tests of test1 and test2 with a more time-consuming TransitionFunction class TFTest2. These also run correctly in the handout code. For assignment 3 you can concentrate on gmake test1 and gmake test2, although gmake test should be able to run all 4 tests successfully in the handout code. Please run gmake test before you make any code changes to ensure that these tests work on arrival, and run gmake test again before turning in assignment 3 and again for assignment 4. Times and generation counts will change with assignment 4, but not in a way that alters the .out files. You can also run an interactive test by invoking gmake testui1 for the TFTest1 TransitionFunction of assignment 2, or gmake testui2 for the new TFTest2 TransitionFunction. An example follows. [:-)] gmake testui1 CLASSPATH=..:~parson/JavaLang/jcip-annotations.jar time java wordca3.WordCAMTM wordca3.TFTest1 80 80 4 Transition function class = wordca3.TFTest1 width,height = 80,80 Transition function class = wordca3.TFTest1 width,height = 80,80 threadcount = 4 from 16 hardware contexts. LOADED OK: wordca3.TFTest1 CA server listening on IPADDR:PORT hermione.kutztown.edu:50000 aX,Y,(a|d|/|\),TEXT or rI(se[c[s]]|ms[ec[s]]st[ates]): In fact, for debugging, an even better way to run the tests interactively is to make the matrix smaller. You can run my solution to assignment 2 in one window and your work-in-progress in another, manually, on small matrices, and compare the step-by-step results. CLASSPATH=..:~parson/JavaLang/jcip-annotations.jar time java wordca3.WordCAMTM wordca3.TFTest1 10 10 4 OR WORDCA_NET_DEBUG=r1st CLASSPATH=..:~parson/JavaLang/jcip-annotations.jar time java wordca3.WordCAMTM wordca3.TFTest1 10 10 4 That second way sets the bash environment variable WORDCA_NET_DEBUG to the string “r1st”. The test driver uses this string in the following way: every time it sees the string “r1st” from the console (i.e., System.in), it issues that command twice, once by calling the interpret() method in the usual way, and also by issuing the command via a client socket connection back into the Server. It gets the results of these commands only after sending them concurrently. Here is an example run of that last command line on Hermione in the handout code. [:-)] WORDCA_NET_DEBUG=r1st CLASSPATH=..:~parson/JavaLang/jcip-annotations.jar time java wordca3.WordCAMTM wordca3.TFTest1 10 10 4 Transition function class = wordca3.TFTest1 width,height = 10,10 Transition function class = wordca3.TFTest1 width,height = 10,10 threadcount = 4 from 16 hardware contexts. LOADED OK: wordca3.TFTest1

Page 4: CSC 543 Multiprocessing & Concurrent Programming, Spring 2015faculty.kutztown.edu/parson/spring2015/csc543spring2015... · 2015-03-14 · CSC 543 Multiprocessing & Concurrent Programming,

page 4

CA server listening on IPADDR:PORT hermione.kutztown.edu:50000 aX,Y,(a|d|/|\),TEXT or rI(se[c[s]]|ms[ec[s]]st[ates]): TESTING TCP/IP incoming on machine:port hermione.kutztown.edu:50000 with command: r1st aX,Y,(a|d|/|\),TEXT or rI(se[c[s]]|ms[ec[s]]st[ates]): a4,4,\,ABC CELL_AT_A_TIME_OUTPUT_NOT_SHOWN V:1,G:1 PICTURE A B C aX,Y,(a|d|/|\),TEXT or rI(se[c[s]]|ms[ec[s]]st[ates]): r1st If you scroll up, you will see two results from this command, one returns via the method call to interpret(), and other returned via a TCP/IP socket: V:1,G:2 PICTURE AAA AAAB AAABC BBBC CCC Here is the second: AWAITING REPLY FROM SERVER GOT REPLY FROM SERVER: V:1,G:3 … V:1,G:3 PICTURE AAAAA AAAAAB AA AABC AAA ABC AAAA BC BBBBBC CCCCC

Invoking the program interactively without WORDCA_NET_DEBUG=r1st in the front avoids sending the r1st a second time via TCP/IP, and changing r1st to a different command duplicates that command instead.

An extremely useful feature of the JVM for debugging multithreaded programs appears next. It is very helpful with programs that lock up. To get the following stack traces of your threads while running a program interactively (System.in and System.out connected to your terminal or putty window), hit ctrl-\ (control backslash, a combined key pair similar to ctrl-C). What follows is the output from ctrl-\ while

Page 5: CSC 543 Multiprocessing & Concurrent Programming, Spring 2015faculty.kutztown.edu/parson/spring2015/csc543spring2015... · 2015-03-14 · CSC 543 Multiprocessing & Concurrent Programming,

page 5

running the above interactive session. There are some JVM-internal threads that I am not showing here. These are the application threads run from within WordCAMTM in the handout code.

Full thread dump OpenJDK 64-Bit Server VM (23.25-b01 mixed mode): "Thread-7" daemon prio=10 tid=0x00002abc2000e000 nid=0x77ea runnable [0x00002abc1e8ea000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(SocketInputStream.java:146) at java.net.SocketInputStream.read(SocketInputStream.java:107) at wordca3.SenderRecver.recv(SenderRecver.java:95) - locked <0x000000075b897ca8> (a wordca3.SenderRecver) at wordca3.WordCAMTM$Server$CnxnHandler$CnxnHelper.run(WordCAMTM.java:617) at java.lang.Thread.run(Thread.java:701) "Thread-6" daemon prio=10 tid=0x00002abc20003800 nid=0x77e9 waiting on condition [0x00002abc1e7e9000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000075af19f98> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043) at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:227) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:355) at wordca3.WordCAMTM$Server$StateWorker.run(WordCAMTM.java:525) at java.lang.Thread.run(Thread.java:701) "Thread-5" daemon prio=10 tid=0x00002abc20001800 nid=0x77e8 waiting on condition [0x00002abc1e6e8000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000075af19f98> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043) at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:227) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:355) at wordca3.WordCAMTM$Server$StateWorker.run(WordCAMTM.java:525) at java.lang.Thread.run(Thread.java:701) "Thread-4" daemon prio=10 tid=0x0000000019a00000 nid=0x77e7 waiting on condition [0x00002abc1e5e7000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000075af19f98> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043) at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:227) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:355) at wordca3.WordCAMTM$Server$StateWorker.run(WordCAMTM.java:525) at java.lang.Thread.run(Thread.java:701) "Thread-3" daemon prio=10 tid=0x000000001999e000 nid=0x77e6 waiting on condition [0x00002abc1e4e6000] java.lang.Thread.State: WAITING (parking)

Page 6: CSC 543 Multiprocessing & Concurrent Programming, Spring 2015faculty.kutztown.edu/parson/spring2015/csc543spring2015... · 2015-03-14 · CSC 543 Multiprocessing & Concurrent Programming,

page 6

at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000075af19f98> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043) at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:227) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:355) at wordca3.WordCAMTM$Server$StateWorker.run(WordCAMTM.java:525) at java.lang.Thread.run(Thread.java:701) "Thread-2" daemon prio=10 tid=0x00002abc140cb000 nid=0x77e5 waiting on condition [0x00002abc1e3e5000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000075af145b0> (a java.util.concurrent.SynchronousQueue$TransferStack) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:451) at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:352) at java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:886) at wordca3.WordCAMTM$Server.run(WordCAMTM.java:231) at java.lang.Thread.run(Thread.java:701) "Thread-1" daemon prio=10 tid=0x00002abc140c9800 nid=0x77e4 runnable [0x00002abc1e2e4000] java.lang.Thread.State: RUNNABLE at java.net.PlainSocketImpl.socketAccept(Native Method) at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:375) at java.net.ServerSocket.implAccept(ServerSocket.java:478) at java.net.ServerSocket.accept(ServerSocket.java:446) at wordca3.WordCAServer.run(WordCAServer.java:84) at java.lang.Thread.run(Thread.java:701) "CArunTimer" daemon prio=10 tid=0x00002abc1409f800 nid=0x77e3 in Object.wait() [0x00002abc1dfcd000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x000000075af14850> (a java.util.TaskQueue) at java.lang.Object.wait(Object.java:502) at java.util.TimerThread.mainLoop(Timer.java:505) - locked <0x000000075af14850> (a java.util.TaskQueue) at java.util.TimerThread.run(Timer.java:484) "main" prio=10 tid=0x00000000198b5000 nid=0x77cd runnable [0x00002abbf93e5000] java.lang.Thread.State: RUNNABLE at java.io.FileInputStream.readBytes(Native Method) at java.io.FileInputStream.read(FileInputStream.java:239) at java.io.BufferedInputStream.read1(BufferedInputStream.java:273) at java.io.BufferedInputStream.read(BufferedInputStream.java:334) - locked <0x000000075aec7f90> (a java.io.BufferedInputStream) at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:282) at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:324) at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:176) - locked <0x000000075af323c8> (a java.io.InputStreamReader) at java.io.InputStreamReader.read(InputStreamReader.java:184) at java.io.Reader.read(Reader.java:100) at java.util.Scanner.readInput(Scanner.java:797) at java.util.Scanner.findWithinHorizon(Scanner.java:1676) at java.util.Scanner.hasNextLine(Scanner.java:1493) at wordca3.WordCAMTM.main(WordCAMTM.java:851)

Page 7: CSC 543 Multiprocessing & Concurrent Programming, Spring 2015faculty.kutztown.edu/parson/spring2015/csc543spring2015... · 2015-03-14 · CSC 543 Multiprocessing & Concurrent Programming,

page 7

Thread-7 and Thread-1 above are two threads associated with active classes that are new to this assignment. Thread-7 class Server.CnxnHandler is an adapter class that accepts incoming connection requests from TCP/IP clients via the new WordCAServer class of Thread-1. It starts an active Server.CnxnHandler.CnxnHelper object for each client connection accepted into the Server by WordCAServer. You do not need to have any knowledge of Java TCP/IP programming to complete this assignment. I have written that code that for you. You can concentrate on the internal structure of WordCAMTM.java; all of your code changes will go there. First half of assignment 3, due by end of Friday March 27. (There is more due on this date below.) Give those application threads sensible names. In fact, use my sensible names as they appear here. Here is what the solution code looks like when I hit ctrl-\ in the above state. Make yours look like this. "CnxnHelper0" prio=10 tid=0x00002ac1d0168800 nid=0x348 runnable [0x00002ac1d4d28000] java.lang.Thread.State: RUNNABLE at java.net.SocketInputStream.socketRead0(Native Method) at java.net.SocketInputStream.read(SocketInputStream.java:146) at java.net.SocketInputStream.read(SocketInputStream.java:107) at wordca3.SenderRecver.recv(SenderRecver.java:95) - locked <0x000000075b897ca0> (a wordca3.SenderRecver) at wordca3.WordCAMTM$Server$CnxnHandler$CnxnHelper.run(WordCAMTM.java:881) at java.lang.Thread.run(Thread.java:701) "StateWorker3" prio=10 tid=0x00002ac1d012d800 nid=0x347 waiting on condition [0x00002ac1d4c27000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000075af1b8d0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043) at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:227) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:355) at wordca3.WordCAMTM$Server$StateWorker.run(WordCAMTM.java:756) at java.lang.Thread.run(Thread.java:701) "StateWorker2" prio=10 tid=0x00002ac1d012b800 nid=0x346 waiting on condition [0x00002ac1d4b26000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000075af1b8d0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043) at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:227) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:355) at wordca3.WordCAMTM$Server$StateWorker.run(WordCAMTM.java:756) at java.lang.Thread.run(Thread.java:701) "StateWorker1" prio=10 tid=0x00002ac1d0129800 nid=0x345 waiting on condition [0x00002ac1d4a25000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000075af1b8d0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043) at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:227) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:355) at wordca3.WordCAMTM$Server$StateWorker.run(WordCAMTM.java:756)

Page 8: CSC 543 Multiprocessing & Concurrent Programming, Spring 2015faculty.kutztown.edu/parson/spring2015/csc543spring2015... · 2015-03-14 · CSC 543 Multiprocessing & Concurrent Programming,

page 8

at java.lang.Thread.run(Thread.java:701) "StateWorker0" prio=10 tid=0x00002ac1d0110000 nid=0x344 waiting on condition [0x00002ac1d4924000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000075af1b8d0> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043) at java.util.concurrent.CyclicBarrier.dowait(CyclicBarrier.java:227) at java.util.concurrent.CyclicBarrier.await(CyclicBarrier.java:355) at wordca3.WordCAMTM$Server$StateWorker.run(WordCAMTM.java:756) at java.lang.Thread.run(Thread.java:701) "Server" prio=10 tid=0x00002ac1d00ed800 nid=0x343 waiting on condition [0x00002ac1d4823000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000075af15460> (a java.util.concurrent.SynchronousQueue$TransferStack) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:451) at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:352) at java.util.concurrent.SynchronousQueue.take(SynchronousQueue.java:886) at wordca3.WordCAMTM$Server.run(WordCAMTM.java:306) at java.lang.Thread.run(Thread.java:701) "StateRunner" prio=10 tid=0x00002ac1d00d3800 nid=0x342 waiting on condition [0x00002ac1d4722000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x000000075af16010> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043) at wordca3.WordCAMTM$Server$StateRunner.run(WordCAMTM.java:545) at java.lang.Thread.run(Thread.java:701) "TCPServer" prio=10 tid=0x00002ac1d00d1800 nid=0x341 runnable [0x00002ac1d4621000] java.lang.Thread.State: RUNNABLE at java.net.PlainSocketImpl.socketAccept(Native Method) at java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:375) at java.net.ServerSocket.implAccept(ServerSocket.java:478) at java.net.ServerSocket.accept(ServerSocket.java:446) at wordca3.WordCAServer.run(WordCAServer.java:84) at java.lang.Thread.run(Thread.java:701) "CArunTimer" daemon prio=10 tid=0x00002ac1d00a6000 nid=0x340 in Object.wait() [0x00002ac1d430a000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x000000075af15700> (a java.util.TaskQueue) at java.lang.Object.wait(Object.java:502) at java.util.TimerThread.mainLoop(Timer.java:505) - locked <0x000000075af15700> (a java.util.TaskQueue) at java.util.TimerThread.run(Timer.java:484) "main" prio=10 tid=0x000000000feed000 nid=0x32a runnable [0x00002ac1af71b000] java.lang.Thread.State: RUNNABLE at java.io.FileInputStream.readBytes(Native Method) at java.io.FileInputStream.read(FileInputStream.java:239) at java.io.BufferedInputStream.read1(BufferedInputStream.java:273) at java.io.BufferedInputStream.read(BufferedInputStream.java:334) - locked <0x000000075aec7f98> (a java.io.BufferedInputStream) at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:282) at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:324) at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:176) - locked <0x000000075af38648> (a java.io.InputStreamReader) at java.io.InputStreamReader.read(InputStreamReader.java:184)

Page 9: CSC 543 Multiprocessing & Concurrent Programming, Spring 2015faculty.kutztown.edu/parson/spring2015/csc543spring2015... · 2015-03-14 · CSC 543 Multiprocessing & Concurrent Programming,

page 9

at java.io.Reader.read(Reader.java:100) at java.util.Scanner.readInput(Scanner.java:797) at java.util.Scanner.findWithinHorizon(Scanner.java:1676) at java.util.Scanner.hasNextLine(Scanner.java:1493) at wordca3.WordCAMTM.main(WordCAMTM.java:1143)

For this one you must find every Thread constructor call in WordCAMTM.java and supply a second argument with a String name that matches mine. The singleton CnxnHandler object starts a new, active CnxnHandler.CnxnHelper object every time the former object’s accept() method runs. Implement a serial counter starting at 0 in some way for the CnxnHelper object’s thread name. Each new incoming socket connection should get the next number for its CnxnHelper active object’s thread. IMPORTANT: ALL OF THE FIELDS I HAVE ADDED IN ASSIGNMENT 3 & 4 SOLUTIONS ARE private AND EITHER final OR volatile. A reference to a mutable object like as AtomicInteger object should be final, even though the object itself is mutable, unless your intent is to store a reference to a different object there at some point in the future. Use final references to both immutable and mutable objects whenever possible. For this assignment, use volatile for fields you intend to change. All of the volatile fields in my handout code and solution are primitive types such as Boolean or long except for “private volatile WordCAState mostRecentGeneration” from assignment 2. Supply GuardedBy annotations if appropriate. Second half of assignment 3, due by end of Friday March 27. (There is more due on this date above.) Change every call to setDaemon(true) that you find in WordCAMTM.java to setDaemon(false). Here is the handout code. $ grep setDaemon WordCAMTM.java serverThread.setDaemon(true); tcpipThread.setDaemon(true); t.setDaemon(true); th.setDaemon(true); Here is my solution. $ grep setDaemon WordCAMTM.java serverThread.setDaemon(false); tcpipThread.setDaemon(false); stateRunnerThread.setDaemon(false); t.setDaemon(false); th.setDaemon(false); Once you do this, your program will hang when the main thread terminates. When running interactively, use ctrl-D (the end-of-file signal) to end terminate input; do NOT use ctrl-C, which just aborts the program. You must NOT add or change any class to System.exit. That library method aborts the process, regardless of whether there are remaining non-daemon threads. Here is the only valid call to System.exit, at the bottom of WordCAMTM.main(), just after a finally clause. if (exitStatus != 0) { System.exit(exitStatus); } That call aborts the process on a non-zero exitStatus, signifying an error further up in the code.

Page 10: CSC 543 Multiprocessing & Concurrent Programming, Spring 2015faculty.kutztown.edu/parson/spring2015/csc543spring2015... · 2015-03-14 · CSC 543 Multiprocessing & Concurrent Programming,

page 10

The idea is that we want to change the current, asynchronous shutdown of daemon threads to the controlled shutdown of a server, including all of its non-daemon threads. Non-daemon threads must terminate without inappropriate error messages when the system is shutting down. We would take this approach if we want various server and worker threads to complete bounded work items before terminating, rather than just by ripping the ground out from beneath daemon threads. Try running gmake testui1 after changing all of the setDaemon(true) calls to setDaemon(false). The process will hang. The other tests will hang, too. Here is the general approach to completing this project:

1. Give every active class a “void shutdown()” method. The method for class WordCAMTM should be public, while the others should be private.

2. For most of these active classes, you can add a volatile boolean field isShutdown initialized to false, and then set it to true in that class’ shutdown method. Also, change any “while (true)” in the run() methods to “while (!isShutdown)”. That will terminate the active object’s Thread (by triggering a return from run()) unless that thread is blocked in a blocking library call.

3. If that thread is blocked in a blocking library call, you must wake it up. You can wake up threads blocked in blocking calls from java.util.concurrent and its subpackages calling the Thread.interrupt() method. There are three methods of interest here:

Thread.interrupt() interrupts a Thread object. Static method Thread.interrupted() returns and clears the interrupted status of the current thread. Non-static method Thread.isInterrupted() returns the interrupted status without clearing it, but you must have a reference to the Thread object to call that one. The only one I used in my solution is Thread.interrupt() to interrupt a Thread object from another thread. Your exception handlers for InterruptedException must now check isShutdown. If it is true in a run() method, that run() method should silently return (without an error message), thereby terminating the thread. Also, any await() in a CylicBarrier may throw a BrokenBarrierException upon receipt of any interrupt. I just made all the exception handlers in my run() methods check isShutdown and silently return from run() when it is true. Returning from run() terminates the non-daemon threads.

4. Active object threads blocked on most I/O library methods do not poll the interrupt status. One place this is relevant in our system is blocking for socket I/O in class CnxnHelper. Take a look at my shutdown method in WordCAServer.java to see how I handled this for the TCP server. I can shut the server socket down concurrently on a non-server thread because the documentation for java.net.ServerSocket.close() says the following.

“Any thread currently blocked in accept() will throw a SocketException.” That documentation asserts thread safety for closing a ServerSocket from one thread while another thread is using the socket. The latter thread will receive a SocketException, which it can then handle. Look to see how WordCAServer.run() handles a SocketException.

5. From the top, public WordCAMTM.shutdown() method, invoke shutdown() on any active object with a field within the WordCAMTM. After calling shutdown on these objects, invoke interrupt() on their threads. This step requires storing both the reference to an active object and a reference to its Thread. Call shutdown() on the active object, then call interrupt() on its thread to deal with the possibility that the thread is blocked on I/O or a synchronization lock.

6. In the private shutdown() methods of these helper classes, do the same thing recursively. Set

Page 11: CSC 543 Multiprocessing & Concurrent Programming, Spring 2015faculty.kutztown.edu/parson/spring2015/csc543spring2015... · 2015-03-14 · CSC 543 Multiprocessing & Concurrent Programming,

page 11

isShutdown to true if it is a field in that class, then call shutdown() on any active objects whose references are stored in that object, and then invoke interrupt() on those object’s Threads. Add code to the exception catch blocks in run() to silently return when isShutdown is true.

7. The StateWorker objects require a little extra work because the handout code does not store references to either these objects nor to their Threads. Take a look at CnxnHandler’s fields and method CnxnHandler.accept() to see one way to keep track of (active object, associated Thread) pairs.

8. In order to trigger a server shutdown, place a call to the WordCAMTM object’s shutdown() method at an appropriate place near the bottom of the WordCAMTM.main method. Do not place it inside the “if (exitStatus != 0)” block. Otherwise, it will not be called when main() returns normally.

When you are ready to test. Run gmake testui1 and hit ctrl-D to send an end-of-file signal into System.in. If the process hangs, hit ctrl-\ to see which application thread(s) are still alive, and where they are running or blocked. I had to do this numerous times while looking for missed or incomplete shutdown() methods. Once you have this working, use gmake test to test everything, and then gmake turnitin by the assignment 3 deadline. I will post assignment 4 in a separate handout. If you want to try out a draft graphical UI for these CAs, download the latest stable Processing framework from https://processing.org/ and run the sketch in the wordca3/sketches/WordCA/ after copying them to your processing directory structure. My Processing setup at home looks like this. I will demo using it in class. Note that you must install a copy of wordca3.jar from our project as a Processing library. ku135515parson:wordca3 parson$ find ~/Documents/Processing -name '[Ww]ord[Cc][Aa]*' -print /Users/parson/Documents/Processing/libraries/wordca3 /Users/parson/Documents/Processing/libraries/wordca3/library/wordca3.jar /Users/parson/Documents/Processing/WordCA /Users/parson/Documents/Processing/WordCA/WordCA.pde

Page 12: CSC 543 Multiprocessing & Concurrent Programming, Spring 2015faculty.kutztown.edu/parson/spring2015/csc543spring2015... · 2015-03-14 · CSC 543 Multiprocessing & Concurrent Programming,

page 12

Here is the part of the Processing sketch WordCA.pde that you may want to modify when you run the sketch: import wordca3.* ; /* * WordCA.pde -- a Processing script to visialize a Word cellular automaton. * STUDENT: At present this visualizer hard codes for an 80 X 80 matrix. * It is a prototype -- I just want to get something running. * This visualizer is not central to Assignment 3, CSC543, Spring 2015. * @author D. Parson */ import java.net.* ; import java.io.* ; private PFont pfont; // STUDENT CAN CHANGE ANY OF THESE CONSTANTS THAT YOU DON'T LIKE. // YOU MAY NEED TO CHANGE TCPPORT BEFORE RUNNING TO MATCH THE SERVER. private final int TCPPORT = 50000 ; // CHANGE this to match the server's port. private boolean tcpbug = false ; private final String [] addCommands = { "a38,39,a,V", /* "a0,0,\\,ABC", "a37,2,/,123", "a77,77,a,VvV" */ }; private int cmdIndex = 0 ; private final String TCPSERVER = "localhost" ; // Test UI on the current machine. private final int MATRIXSIZE = 80 ; private final int POINTSIZE = 14 ; private final int FRAMERATE = 30 ; // This many graphical frames per second. private final int ERASERATE = 150 ; // 0..255 private final int STATESTEPS = 1 ; // advance STATESTEPS every time … This Processing script with these values for the configuration values sends "a38,39,a,V", to the CA server and then sends “r1st” every 30th of a second for this FRAMERATE = 30. First you must run gmake testui1 from a terminal window, and then start this Processing script on the same machine. Only the next page is a static screen shot many generations into the evolution of the CA. The Processing script currently hard codes for an 80 x 80 grid and ignores the rotatez parameter of each LetterAtom. You can also try gmake testui2 and then run Processing to see the other TransitionFunction. If you don’t have GNU make, just run the corresponding commands lines that you see on harry when running gmake testui1 or gmake testui2.

Page 13: CSC 543 Multiprocessing & Concurrent Programming, Spring 2015faculty.kutztown.edu/parson/spring2015/csc543spring2015... · 2015-03-14 · CSC 543 Multiprocessing & Concurrent Programming,

page 13

The final thing that I want to go over briefly in this handout is the new helper class that allows clients of a CA to submit commands and then collect results, asynchronously, some time later. You will need to know about this class for assignment 4, but since you will see it while working on assignment 3, I think it is worth understanding now. It is in file CommandAndContinuation.java and is complete. The code appears below. We will go over it in class. 1 package wordca3 ; 2 import java.util.concurrent.BlockingQueue ; 3 import net.jcip.annotations.* ; 4 5 /** 6 * CommandAndContinuation provides a way to run a command that delivers 7 * its result some time later, without blocking until interpretation 8 * of the command is complete. A CommandAndContinuation object provides 9 * both the result and trouble fields for returning successful and 10 * exceptional results respectively, and a resultQueue in which to 11 * deliver a CommandAndContinuation that records a result. 12 * Fields are public because this is basically a simple data 13 * container. It is not immutable because the resultQueue is 14 * mutable; resultQueue must be a thread-safe object. 15 * @author D. Parson

Page 14: CSC 543 Multiprocessing & Concurrent Programming, Spring 2015faculty.kutztown.edu/parson/spring2015/csc543spring2015... · 2015-03-14 · CSC 543 Multiprocessing & Concurrent Programming,

page 14

16 **/ 17 @ThreadSafe 18 public class CommandAndContinuation 19 implements Comparable<CommandAndContinuation> { 20 /** deadline for when the cmd will finish, either in a millisecond 21 * clock in relation to java.lang.System.currentTimeMillis(), or 22 * in the value in a WordCAState.generation field. It is up to 23 * the application that uses this class to interpret the deadline. 24 * @see WordCAState#generation 25 **/ 26 public final long deadline ; 27 /** This is the command. **/ 28 public final String cmd ; 29 /** Field to store a non-exceptional result, null when cmd is new. **/ 30 public final WordCAState result ; 31 /** Field to store a exceptional result, null when cmd is new. **/ 32 public final Exception trouble ; 33 /** 34 * Where to send the result or trouble as a reply. 35 * resultQueue must be a thread-safe queue object. 36 **/ 37 public final BlockingQueue<CommandAndContinuation> resultQueue ; 38 /** 39 * Construct the initial command to interpret. 40 * @param deadline in relation to java.lang.System.currentTimeMillis() 41 * or in a WordCAState.generation fields, use negative when unknown. 42 * @param cmd is the command. 43 * @param resultQueue is where to send the result back to the caller. 44 * resultQueue must be a thread-safe queue object. 45 **/ 46 public CommandAndContinuation(long deadline, String cmd, 47 BlockingQueue<CommandAndContinuation> resultQueue) { 48 this.deadline = deadline ; 49 this.cmd = cmd ; 50 result = null ; 51 trouble = null ; 52 this.resultQueue = resultQueue ; 53 } 54 /** 55 * Make a clone of a former CommandAndContinuation with a result. 56 * @param former is the former state of the CommandAndContinuation. 57 * @param result is its result. 58 * @param deadline in relation to java.lang.System.currentTimeMillis() 59 * or in a WordCAState.generation fields, use negative when unknown. 60 **/ 61 public CommandAndContinuation(CommandAndContinuation former, 62 WordCAState result, long deadline) { 63 this.deadline = deadline ; 64 this.cmd = former.cmd ; 65 this.result = result ; 66 this.trouble = former.trouble ; 67 this.resultQueue = former.resultQueue ; 68 } 69 /** 70 * Make a clone of a former CommandAndContinuation with an exception. 71 * @param former is the former state of the CommandAndContinuation.

Page 15: CSC 543 Multiprocessing & Concurrent Programming, Spring 2015faculty.kutztown.edu/parson/spring2015/csc543spring2015... · 2015-03-14 · CSC 543 Multiprocessing & Concurrent Programming,

page 15

72 * @param trouble is its exception. 73 * @param deadline in relation to java.lang.System.currentTimeMillis() 74 * or in a WordCAState.generation fields, use negative when unknown. 75 **/ 76 public CommandAndContinuation(CommandAndContinuation former, 77 Exception trouble, long deadline) { 78 this.deadline = deadline ; 79 this.cmd = former.cmd ; 80 this.result = former.result ; 81 this.trouble = trouble ; 82 this.resultQueue = former.resultQueue ; 83 } 84 /** 85 * Compare this to other based on contract of java.lang.Comparable. 86 * Sort is ascending based only on the deadline field. 87 * @param other is the other field for comparison, 88 * must be non-null. 89 * @return -1, 0 or 1 according to the contract of 90 * java.lang.Comparable.compareTo 91 **/ 92 @Override 93 public int compareTo(CommandAndContinuation other) { 94 if (this.deadline == other.deadline) { 95 return 0 ; 96 } else if (this.deadline < other.deadline) { 97 return -1 ; 98 } else { 99 return 1 ; 100 } 101 } 102 /** 103 * Redefined equals to compare only the deadline field, 104 * useful for sorting these objects in a priority queue. 105 * @param obj is other object for comparison based on the 106 * deadline field, must be a non-null instance of 107 * class CommandAndContinuation 108 * @return true if deadline fields are ==, else false. 109 **/ 110 @Override 111 public boolean equals(Object obj) { 112 return (obj instanceof CommandAndContinuation 113 && (((CommandAndContinuation)obj).deadline 114 == this.deadline)); 115 } 116 /** Make hashCode() depend only one deadline field. **/ 117 public int hashCode() { 118 return (new Long(deadline)).hashCode(); 119 } 120 }


Recommended