Project 2 Overview (Threads in Practice)

Download Report

Transcript Project 2 Overview (Threads in Practice)

Project 2 Overview
(Threads in Practice)
CSE451
Andrew Whitaker
Project 2 Overview
Project consists of threaded Java programs
No VMWare / kernel hacking
You can use any multi-processor Linux
machine
Most (all?) undergrad lab machines are dual core
Also, you have access to amlia.cs.washington.edu
Run ‘more /proc/cpuinfo’ to verify
Continue to work in your project teams
General Instructions
 Your programs must use proper synchronization
 Working functionality is not enough!
 Remember the rules we’ve talked about:
 All shared, mutable state must be properly synchronized
 Usually with a synchronized block or method
 Compound actions must be protected by a single lock
 Start early!
 Not a huge amount of code, but a lot of new concepts
 Thursday’s discussion will be Q & A
Using Other People’s Code
Do it!
e.g., java.util.LinkedList, java.util.ArrayList, …
But, understand the implications for
threading
May require documentation diving
Part 1: Implementing Semaphores
 Semaphore is a thread-safe integer
 Supports up and down operations for increment
/ decrement
 The semaphore can never go negative
If value == 0, then down blocks before decrementing
 Thread is added to a wait queue
If value == 0, then up wakes up a thread after
incrementing
 Semaphore with value 1 is a lock
Pseudocode
public class Semaphore {
private int count;
// block if count == 0
// else, decrement
public void down () { }
// increment count
// wake up somebody (if necessary)
public void up () { }
}
Semaphores, Continued
 Condition variables and semaphores have
equivalent expressive power
One can be implemented with the other
 Your task: demonstrate this with Java code
Your solution should not busy wait
 Do not use java.util.concurrent.Semaphore
Or any other off-the-shelf semaphore implementation
Part 2: Calculating 
Step 1: approximate  using a random
number generator
Step 2: Convert this program to a multithreaded program
Step 3: Benchmark the program with a
variable number of threads
 Approximation Hint
Consider a circle
inscribed in a square
Imagine throwing a large
number of darts at the
square
Some fraction of darts will
also hit the circle
Use this fraction to calculate

Multi-threaded  Calculator
Approximating  requires many samples
10s of millions is a reasonable starting point
So, let’s try decomposing the work across
multiple threads
public double calculate(int numSamples, int numThreads) {
return 0.0; // TODO: implement this!
}
Mapping This to Code
Java’s Thread join method is useful for
these sorts of computations
public double calculate(int numSamples, int numThreads) {
Thread [] threads = new Thread[numThreads];
for (int i=0;i <= numThreads; i++) {
threads[i] = new WorkerThread(…);
threads[i].start();
}
for (int i=0;i <= numThreads; i++) {
try {
threads[i].join(); // wait for thread termination
}
catch (InterruptedException ie) {} //ignored
}
}
Benchmarking
Create a graph with # threads on the xaxis and latency on the y-axis
Let threads range from 1 to 10
Number of samples should be fixed
Each thread does a fraction of the total samples
Measure latency with
System.currentTimeMillis()
Part 3: Multi-threaded Web Server
 Task: convert a single-threaded web server to a
multi-threaded web server
 Why?
Any high-throughput web server must handle multiple
requests in parallel
By default, each thread handles one request at a time
Requests are blocking
 Thread is stalled while waiting for network, disk, etc.
Anatomy of a (Single-threaded)
Web Server
while (true) {
1. Accept a new Socket
2. Read from socket to extract
request URI (e.g., index.html)
3. Read desired file into a buffer
4. Write file over the socket
5. Close the socket
}
These are
blocking calls
Possible Alternate Approach: Threadper-request
while (true) {
1. Accept a new Socket
2. Fork a thread
}
1. Read from socket
2. Read desired file into a buffer
3. Write file over the socket
4. Close the socket
5. Thread exits
Analysis of Thread-per-Request
Advantage: supports simultaneous
requests (and higher throughput)
Blocking operations only stall one thread
Disadvantages:
Thread creation is expensive
Must create PCB, allocate stack
Thread teardown is expensive
Too many threads can lead to poor
performance
Preferred Solution: Thread Pool
 On startup, create a static
pool of worker threads
 Each thread loops forever,
processing requests
 Advantages:
Thread allocation cost is paid
only once
Threads are never deallocated
Thread Pool, Implementation
Overview
while (true) {
1.
2.
Accept a new Socket
Enqueue Socket
while (true) {
}
1.
2.
3.
4.
5.
Accept thread
Dequeue Socket
Read from socket
Read desired file into a buffer
Write file over the socket
Close the socket
}
Worker threads
Web Server, Continued
Step 2: Add a “statistics” page at
http://hostname/STATS
Req/sec over the previous ten seconds
Number of currently active threads
Number of idle threads
Step 3: Benchmark the web server
Using the provided benchmark tool
Java Timers
See lecture or condition variables
OR, java.util.Timer and java.util.TimerTask
Key point: timers run in a separate thread
So, shared state must be properly synchronized
Part 4: GUI Hacking
We provide a simple GUI for calculating
the first N fibonacci numbers
You provide an implementation of the
cancel button
Challenge
Problem: GUI frameworks are singlethreaded
Long-lived computations can make the GUI
unresponsive
Solution: Transfer long-lived tasks to a
separate thread
Requires coordination between the GUI thread
and the helper thread
Things You Need to Understand
How task handoff works in the Swing GUI
framework?
In particular, SwingUtilities.invokeLater
How does thread interruption work?
Via Thread.interrupt
Thread Interruption
You can call interrupt on any Thread
What happens?
If the thread was blocked, it receives an
InterruptedException
 If the thread is ready or running, it has an
interrupted flag set
The thread must explicitly check this flag with
Thread.isInterrupted