Test-First Java Concurrency for the Classroom SIGCSE 2010 Mathias Ricken and Robert Cartwright Rice University March 12, 2009.

Slides:



Advertisements
Similar presentations
– R 7 :: 1 – 0024 Spring 2010 Parallel Programming 0024 Recitation Week 7 Spring Semester 2010.
Advertisements

Practice Session 7 Synchronization Liveness Deadlock Starvation Livelock Guarded Methods Model Thread Timing Busy Wait Sleep and Check Wait and Notify.
Chapter 6: Process Synchronization
Concurrency 101 Shared state. Part 1: General Concepts 2.
CS 5704 Fall 00 1 Monitors in Java Model and Examples.
/ PSWLAB Concurrent Bug Patterns and How to Test Them by Eitan Farchi, Yarden Nir, Shmuel Ur published in the proceedings of IPDPS’03 (PADTAD2003)
ConcJUnit: Unit Testing for Concurrent Programs PPPJ 2009 Mathias Ricken and Robert Cartwright Rice University August 28, 2009.
Java How to Program, 9/e CET 3640 Professor: Dr. José M. Reyes Álamo © Copyright by Pearson Education, Inc. All Rights Reserved.
Concurrency and Thread Yoshi. Two Ways to Create Thread Extending class Thread – Actually, we need to override the run method in class Thread Implementing.
Threading Part 3 CS221 – 4/24/09. Teacher Survey Fill out the survey in next week’s lab You will be asked to assess: – The Course – The Teacher – The.
Threading Part 2 CS221 – 4/22/09. Where We Left Off Simple Threads Program: – Start a worker thread from the Main thread – Worker thread prints messages.
Synchronization in Java Nelson Padua-Perez Bill Pugh Department of Computer Science University of Maryland, College Park.
Synchronization in Java Fawzi Emad Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
Threads A thread is a program unit that is executed independently of other parts of the program A thread is a program unit that is executed independently.
Multithreading in Java Nelson Padua-Perez Chau-Wen Tseng Department of Computer Science University of Maryland, College Park.
Race Conditions CS550 Operating Systems. Review So far, we have discussed Processes and Threads and talked about multithreading and MPI processes by example.
Java How to Program, 9/e CET 3640 Professor: Dr. Reyes Álamo © Copyright by Pearson Education, Inc. All Rights Reserved.
Multithreading.
50.003: Elements of Software Construction Week 5 Basics of Threads.
Testing Concurrent Programs COMP Production Programming Mathias Ricken Rice University Spring 2009.
Unit Testing in Java with an Emphasis on Concurrency Corky Cartwright Rice and Halmstad Universities Summer 2013.
1 Advanced Computer Programming Concurrency Multithreaded Programs Copyright © Texas Education Agency, 2013.
1 CSCD 330 Network Programming Lecture 13 More Client-Server Programming Sometime in 2014 Reading: References at end of Lecture.
Nachos Phase 1 Code -Hints and Comments
Object Oriented Programming Lecture 8: Introduction to laboratorial exercise – part II, Introduction to GUI frames in Netbeans, Introduction to threads.
Threads. Java Threads A thread is not an object A thread is a flow of control A thread is a series of executed statements A thread is a nested sequence.
Threading and Concurrency Issues ● Creating Threads ● In Java ● Subclassing Thread ● Implementing Runnable ● Synchronization ● Immutable ● Synchronized.
Multithreading in Java Project of COCS 513 By Wei Li December, 2000.
Java Threads 11 Threading and Concurrent Programming in Java Introduction and Definitions D.W. Denbo Introduction and Definitions D.W. Denbo.
111 © 2002, Cisco Systems, Inc. All rights reserved.
Practical OOP using Java Basis Faqueer Tanvir Ahmed, 08 Jan 2012.
Multithreading : synchronization. Avanced Programming 2004, Based on LYS Stefanus’s slides slide 4.2 Solving the Race Condition Problem A thread must.
Java Threads. What is a Thread? A thread can be loosely defined as a separate stream of execution that takes place simultaneously with and independently.
Testing Concurrent Programs, A 7-Minute Jargon-Free Introduction Thesis Writing Seminar Mathias Ricken Rice University February 25, 2010.
CS 346 – Chapter 4 Threads –How they differ from processes –Definition, purpose Threads of the same process share: code, data, open files –Types –Support.
1 A Framework for Testing Concurrent Programs PhD Thesis Defense Mathias Ricken Rice University January 10, 2011.
Optimistic Design 1. Guarded Methods Do something based on the fact that one or more objects have particular states  Make a set of purchases assuming.
Operating Systems ECE344 Ashvin Goel ECE University of Toronto Mutual Exclusion.
Internet Software Development Controlling Threads Paul J Krause.
A Framework for Testing Concurrent Programs COMP 600 Mathias Ricken Rice University August 27, 2007.
A Framework for Testing Concurrent Programs MS Thesis Defense Mathias Ricken Rice University June 14, 2007.
CSC321 Concurrent Programming: §5 Monitors 1 Section 5 Monitors.
Kernel Locking Techniques by Robert Love presented by Scott Price.
ICS 313: Programming Language Theory Chapter 13: Concurrency.
Chapter 6 – Process Synchronisation (Pgs 225 – 267)
Advanced Concurrency Topics Nelson Padua-Perez Bill Pugh Department of Computer Science University of Maryland, College Park.
Java Thread and Memory Model
Concurrency Control 1 Fall 2014 CS7020: Game Design and Development.
Threads in Java1 Concurrency Synchronizing threads, thread pools, etc.
Multithreaded programming  Java provides built-in support for multithreaded programming. A multithreaded program contains two or more parts that can run.
Threads. Objectives You must be able to answer the following questions –What code does a thread execute? –What states can a thread be in? –How does a.
CS533 – Spring Jeanie M. Schwenk Experiences and Processes and Monitors with Mesa What is Mesa? “Mesa is a strongly typed, block structured programming.
1 A Framework for Testing Concurrent Programs PhD Proposal Mathias Ricken Rice University December 2, 2010.
ConcJUnit: Unit Testing for Concurrent Programs COMP 600 Mathias Ricken Rice University August 24, 2009.
Concurrency (Threads) Threads allow you to do tasks in parallel. In an unthreaded program, you code is executed procedurally from start to finish. In a.
Concurrency in Java MD. ANISUR RAHMAN. slide 2 Concurrency  Multiprogramming  Single processor runs several programs at the same time  Each program.
Mutual Exclusion -- Addendum. Mutual Exclusion in Critical Sections.
Concurrent Programming in Java Based on Notes by J. Johns (based on Java in a Nutshell, Learning Java) Also Java Tutorial, Concurrent Programming in Java.
Java Thread Programming
Multithreading / Concurrency
Threads Chate Patanothai.
Definitions Concurrent program – Program that executes multiple instructions at the same time. Process – An executing program (the running JVM for Java.
Multithreading.
Multithreading.
Dr. Mustafa Cem Kasapbaşı
Java Concurrency.
Java Concurrency.
CSE 332: Concurrency and Locks
Testing Concurrent Programs
Threads and concurrency / Safety
Presentation transcript:

Test-First Java Concurrency for the Classroom SIGCSE 2010 Mathias Ricken and Robert Cartwright Rice University March 12, 2009

2 Two Trends Test-driven developmentConcurrent programming Brian Goetz, Java Concurrency in Practice, Addison-Wesley, 2006

3 Unit Testing Benefits Occurs early Automates testing Keeps the shared repository clean Prevents bugs from reoccurring Allows safe refactoring Serves as documentation

4 Unit Testing in Assignments Hand out test cases to students –Improves confidence and understanding Instill good practices –Require students to extend test suites Automated grading –Part graded automatically, part by hand

5 Moore’s Law Requires Concurrency Adopted from Sutter 2009

6 Concurrency Is Difficult Unit testing not effective in multi-threaded programs

7 Existing Unit Testing Frameworks JUnit, TestNG Don’t detect test failures in threads other than main thread –Failures in event thread not detected either Don’t ensure that other threads terminate Tests that should fail may succeed

8 Sample JUnit Tests public class SimpleTest extends TestCase { public void testException() { throw new RuntimeException("booh!"); } public void testAssertion() { assertEquals(0, 1); } } if (0!=1) throw new AssertionFailedError(); } Both tests fail.

9 JUnit Test with Child Thread public class SimpleTest extends TestCase { public void testException() { new Thread() { public void run() { throw new RuntimeException("booh!"); } }.start(); } new Thread() { public void run() { throw new RuntimeException("booh!"); } }.start(); throw new RuntimeException("booh!"); Main thread Child thread Main thread Child thread spawns uncaught! end of test success! Uncaught exception, test should fail but does not!

10 ConcJUnit Backward compatible replacement for JUnit Detects exceptions in all threads –Exception handler for all child threads and the event thread Ensures that child threads have terminated and event thread is done –Enumerate live threads after test –Inspect event queue Requires all child threads to be joined –Analyze join graph

11 Thread Creation Coordinates In Thread.start() record stack trace of Thread.currentThread() –Easy to find where a thread that caused a failure was started –Also shows where threads that outlived the test were started

12 Creation Coordinates Example class Main { void foo() { // which one? new Helper(true).start(); new Helper(false).start(); //... } AssertionError: at Helper.m(Helper.java:2) at Helper.run(Helper.java:3) Started at: at Main.foo(Main.java:4) at Main.bar(Main.java:15) at Main.main(Main.java:25) class Helper extends Thread { void m() { if (b) Assert.fail(); } public void run() { m(); } private boolean b; // … }

13 ConcJUnit Demo

14 Concurrency Examples In-class discussion –Multi-threaded counter: data races –Multi-threaded bank: deadlock Homework –Bounded buffer –Readers-writer lock –Test suite handed out to help students Multi-threaded Breakout

15 Example: Counter Class that can increment an integer variable N times Write test first public class CounterTest extends TestCase { final long PER_THREAD = ; public void testSingle() { Counter c = new Counter(); c.incrementNTimes(PER_THREAD); assertEquals(PER_THREAD, c.getCount()); }

16 Counter: Implementation Write implementation public class Counter { private long count = 0; public long getCount() { return count; } public void incrementNTimes(long n) { for(long i=0; i<n; ++i) { ++count; } } Test passes!

17 Counter: Multi-threaded Test Write multi-threaded test public void testMulti() { final Counter c = new Counter(); for(int i=0; i<NUM_THREADS; ++i) { new Thread() { public void run() { c.incrementNTimes(PER_THREAD); } }.start(); } TestUtils.waitForOtherThreads(); assertEquals(NUM_THREADS*PER_THREAD,c.getCount()); } Test fails (most likely)!

18 Shared Data Why does the multi-threaded counter tes t fail? –The count field is shared among threads –The ++count operation is not atomic –Thread may be interrupted after reading count, but before writing back to count count=0 regA=? regB=? A1 regA = count; 00? B1 regB = count; 000 A2 regA = regA + 1;010 A3 count = regA;110 B2 regB = regB + 1;111 B3 count = regB;111

19 Data Races Definition –Two threads access the same data –At least one access is a write –Nothing prevents the order from changing Would like code to execute atomically (without interruption) –Java does not support atomicity (for general code)

20 Java Locks & Synchronized Java provides “lock objects” and synchronized blocks synchronized(lock) { ++count; } –Thread must compete for ownership of lock object before entering synchronized block –Synchronized block is not atomic –But once a thread has a lock object, no other thread can execute code protected by the same lock object

21 Counter: Re-Write Rewrite implementation //... private Object lock = new Object(); public void incrementNTimes(long n) { for(long i=0; i<n; ++i) { synchronized(lock) { ++count; } } Test passes!

22 Concurrency Still Difficult Even race-free, deadlock-free programs are not deterministic –Thread scheduling is essentially non- deterministic Different schedules may compute different results –May or may not be acceptable, depending on the task

23 Multi-threaded Breakout Uses ACM Java Task Force material –Based on “Breakout - Nifty Assignment” by Eric Roberts, SIGCSE 2006 Multiple balls, each in its own thread –Atomicity assumption when removing bricks –Ends game before all bricks are removed Other problems –X,Y coordinate changes not atomic –X,Y coordinates not volatile or synchronized, event thread may never see the updates Correctly synchronized version still not deterministic

24 Future Work Testing all schedules is intractable Insert random delays/yields before synchronization operations –Must consider volatile variable accesses to comply with Java Memory Model –Re-run program several times –Can detect a number of sample problems Record schedule, replay if test fails –Makes failures reproducible if found *3

25 Conclusion Unit testing has important benefits in industry and in the classroom Concurrent programming is becoming more important, and it’s difficult ConcJUnit helps…

Notes

27 Notes 1.Also cannot detect uncaught exceptions in a program’s uncaught exception handler (JLS limitation) ←← 2.Only add edge if joined thread is really dead; do not add if join ended spuriously. ←← 3.Have not studied probabilities or durations for sleeps/yields: One inserted delay may negatively impact a second inserted delay Example: If both notify() and wait() are delayed. ←←

28 public class Test extends TestCase { public void testException() { Thread t = new Thread(new Runnable() { public void run() { throw new RuntimeException("booh!"); } }); t.start(); while(t.isAlive()) { try { t.join(); } catch(InterruptedException ie) { } } Thread t = new Thread(new Runnable() { public void run() { throw new RuntimeException("booh!"); } }); t.start(); while(t.isAlive()) { try { t.join(); } catch(InterruptedException ie) { } } throw new RuntimeException("booh!"); Loop since join() may end spuriously 4. ←← Spurious Wakeup

Image Attribution

30 Image Attribution 1.Left image on Two Trends: Test Driven Development, Damian Cugley.Two TrendsTest Driven Development 2.Right image on Two Trends: adapted from Brian Goetz et al. 2006, Addison Wesley.Two TrendsBrian Goetz et al. 2006, Addison Wesley 3.Graph on Moore’s Law: Adapted from Herb Sutter 2009Moore’s LawHerb Sutter Image on Concurrency Is Difficult: Caption FridaysConcurrency Is Difficult Caption Fridays

Extra Slides

32 Changes to JUnit (1 of 3) Thread group with exception handler –JUnit test runs in a separate thread, not main thread –Child threads are created in same thread group –When test ends, check if handler was invoked Reasoning: Uncaught exceptions in all threads must cause failure

33 JUnit Test with Child Thread public class Test extends TestCase { public void testException() { new Thread(new Runnable() { public void run() { throw new RuntimeException("booh!"); } }).start(); } new Thread(new Runnable() { public void run() { throw new RuntimeException("booh!"); } }).start(); throw new RuntimeException("booh!"); invokes checks TestGroup’s Uncaught Exception Handler

34 JUnit Test with Child Thread public class Test extends TestCase { public void testException() { new Thread() { public void run() { throw new RuntimeException("booh!"); } }.start(); } new Thread() { public void run() { throw new RuntimeException("booh!"); } }.start(); throw new RuntimeException("booh!"); Test thread Child thread uncaught! end of test Main thread spawns and joinsresumes check exception handler invokes exception handler failure!

35 Child Thread Outlives Parent public class Test extends TestCase { public void testException() { new Thread() { public void run() { throw new RuntimeException("booh!"); } }.start(); } new Thread() { public void run() { throw new RuntimeException("booh!"); } }.start(); throw new RuntimeException("booh!"); Test thread Child thread uncaught! end of test success! invokes exception handler Main thread check exception handler Too late!

36 Changes to JUnit (2 of 3) Check for living child threads after test ends Reasoning: Uncaught exceptions in all threads must cause failure If the test is declared a success before all child threads have ended, failures may go unnoticed Therefore, all child threads must terminate before test ends

37 Check for Living Child Threads public class Test extends TestCase { public void testException() { new Thread() { public void run() { throw new RuntimeException("booh!"); } }.start(); } new Thread() { public void run() { throw new RuntimeException("booh!"); } }.start(); throw new RuntimeException("booh!"); Test thread Child thread uncaught! end of test failure! invokes group’s handler Main thread check for living child threads check group’s handler

38 Correctly Written Test public class Test extends TestCase { public void testException() { Thread t = new Thread() { public void run() { /* child thread */ } }; t.start(); t.join(); } Thread t = new Thread() { public void run() { /* child thread */ } }; t.start(); t.join(); // wait until child thread has ended /* child thread */ Test thread Child thread end of test success! Main thread check for living child threads check group’s handler *4

39 Changes to JUnit (3 of 3) Check if any child threads were not joined Reasoning: All child threads must terminate before test ends Without join() operation, a test may get “lucky” Require all child threads to be joined

40 Fork/Join Model Parent thread joins with each of its child threads May be too limited for a general-purpose programming language Child thread 1 Child thread 2 Main thread

41 Example of Other Join Models Chain of child threads guaranteed to outlive parent Main thread joins with last thread of chain Child thread 1 Child thread 2 Main thread Child thread 3

42 Modifying the Java Runtime Changing Thread.start() and join() –Need to modify Java Runtime Library –Utility to process user’s rt.jar file –Put new jar file on boot classpath: -Xbootclasspath/p:newrt.jar Still works without modified Thread class –Just does not emit “lucky” warnings

43 Join with All Offspring Threads Main thread joins with all offspring threads, regardless of what thread spawned them Child thread 1 Child thread 2 Main thread

44 Generalize to Join Graph Threads as nodes; edges to joined thread Test is well-formed as long as all threads are reachable from main thread Child thread 1 Child thread 2 Main thread Child thread 3 MT CT1 CT2 CT3

45 Child thread 1 Child thread 2 Main thread MT CT1 CT2 Child thread 1 Child thread 2 Main thread MT CT1 CT2 Join Graph Examples

46 Child thread 1 Child thread 2 Main thread MT CT1 CT2 Unreachable Nodes An unreachable node has not been joined –Child thread may outlive the test

47 child Thread main Thread MT CT Constructing the Graph // in mainThread childThread.start(); Add node for childThread

48 // in mainThread childThread.join(); When leaving join(), add edge from mainThread to childThread child Thread main Thread MT CT Constructing the Graph *2

49 Example: Multi-threaded Bank Program simulating checking accounts Account balances are shared data –To avoid data races, use synchronized –Need access to two accounts for transfers synchronized(locks[from]) { synchronized(locks[to]) { accounts[from] -= amount; accounts[to] += amount; } Test hangs!

50 Deadlock Thread A transfers from account 0 to 1 Thread B transfers from account 1 to 0 Thread A gets interrupted after acquiring locks[0] // thread A // thread B synchronized(locks[0]) { synchronized(locks[1]) { synchronized(locks[0]) // can’t continue, locks[0] // is owned by thread A */ synchronized(locks[1]) // can’t continue, locks[1] // is owned by thread B */

51 Lock Acquisition Order No deadlock if both threads had attempted to acquire lock 0 first When acquiring more than one lock object, always acquire them in the same order –e.g. acquire lower account’s lock object first synchronized(locks[Math.min(from,to)]) { synchronized(locks[Math.max(from,to)]) { accounts[from] -= amount; accounts[to] += amount; }

52 Homework Assignment Common structures students will see time and again –Bounded buffer –Readers-writer lock Grade correctness and efficiency, e.g. –Maximize concurrency –Only wake up as few threads as possible Provide students with test suites

53 Many Thanks To… My advisor –Corky Cartwright My committee members –Walid Taha –David Scott –Bill Scherer NSF and Texas ATP –For providing partial funding