230 likes | 334 Views
The Zen of Threads. 3 Types of Execution. Single, lone process doing all the work No problems with multiple-access Can be inconvenient/inefficient -- blocking, single-user, etc. Multiple processes, possibly communicating via sockets/files/FIFOs (traditional UNIX model)
E N D
3 Types of Execution • Single, lone process doing all the work • No problems with multiple-access • Can be inconvenient/inefficient -- blocking, single-user, etc. • Multiple processes, possibly communicating via sockets/files/FIFOs (traditional UNIX model) • More efficient; no blocking, >1 user, etc. • Hard to share data (all in terms of messages) • No synchronization problems • Threads • Efficient; no blocking, >1 user, etc. • Synchronization & data sharing tricky
The Weakness of One Process public class mySwingApp { public static void main(String[] args) { mySwingApp app=new mySwingApp(args); app._init(); } private void _init() { JFrame jf=_buildGui(); jf.pack(); jf.setVisible(true); } // more GUI initialization private class _buttonHandler { public void actionPerformed(ActionEvent e) { if (e.getCommand().equals(“Connect to Web Site”)) { // look up web site; read data from it; store // data in memory } }
The Weakness of One Process • Problem 1: If any subroutine takes a long time, everything else (including UI) will have to wait for it (blocking) • Typical blocking operations • I/O • Network communication • expensive computation (PuzzleMuncher) • Problem 2: no support for multiuser app/OS • Pure batch mode • Can’t have >1 person talk to DB/web page/etc. at a time
The Multi-Process Model • Process (in UNIX sense) is a separate program, running in its own memory space, independent from every other program/process • Process has its own copy of code, its own PC, own stack & heap, etc. • Separation enforced by kernel & hardware • All resource sharing passes through kernel • Sockets, files, pipes, FIFOs, etc. • New proc created (in UNIX) w/ fork()
The Multi-Process Model proc 0 proc 1 proc 2 text text text PC addi $0, 3 bne $3, $4, 23 nop mult $7, $19 mflo $3 sw $3, $11 ... addi $0, 3 bne $3, $4, 23 nop mult $7, $19 mflo $3 sw $3, $11 ... addi $0, 3 bne $3, $4, 23 nop mult $7, $19 mflo $3 sw $3, $11 ... PC PC stack heap stack heap stack heap obj0 obj0 obj1 obj1 obj1 objN-1 objN objN objN memory
Inter-Process Communication proc 0 proc 1 text text addi $0, 3 bne $3, $4, 23 nop mult $7, $19 mflo $3 sw $3, $11 ... addi $0, 3 bne $3, $4, 23 nop mult $7, $19 mflo $3 sw $3, $11 ... PC PC stack heap stack heap obj0 obj0 obj1 obj1 objN-1 objN objN memory pipe.write() pipe.read() pipe.write() pipe.read()
The Multi-Thread Model • Threads run within a single process • Each thread has its own • Program Counter • Registers • Stack (subroutine local vars) • All threads share • Memory (all objects in common) • Program code (same methods/subroutines) • No kernel/hardware separation (!) -- all separation done by programmer (you!)
The Multi-Thread Model thread 2 thread 1 thread 0 PC PC PC registers registers registers stack stack stack memory proc 0 text addi $0, 3 bne $3, $4, 23 nop mult $7, $19 mflo $3 sw $3, $11 ... heap obj0 obj2 objN-2 obj1 obj3 objN-3 objN objN-1
Inter-Thread Communication thread 2 thread 1 thread 0 PC PC PC registers registers registers stack stack stack memory proc 0 text addi $0, 3 bne $3, $4, 23 nop mult $7, $19 mflo $3 sw $3, $11 ... heap obj0 obj2 objN-2 obj1 obj3 objN-3 objN objN-1
The Joy & Danger of Threads • All threads share same data • Communication is trivial • All threads share same data • Easy to stomp on another thread’s data! • Two threads can write to same location at same time, or one can write & one can read • Can violate pre/post conditions of methods • => Inconsistent data state • Have to synchronize accesses to ensure only one thread is meddling w/ important data at a time
Example Thread Data Corruption private int[] _multArray[] = new int[128]; private constructor() { for (int i=0;i<_multArray.length;++i) { _multArray[i]=i; } } private void _seedArray(int s) { for (int i=0;i<_multArray.length;++i) { _multArray[i]=i*s; } } private void _writeToFile() { _myFile.print(“_multArray=[ “); for (int i=0;i<_multArray.length;++i) { _myFile.print(_multArray[i] + “ “); } _myFile.println(“]”); }
Example Thread Data Corruption _multArray _multArray _multArray After constructor() 0 1 2 3 4 5 6 7 8 9 10 11 12 After _seedArray(2) 0 2 4 6 8 10 12 14 16 18 20 22 24 After _seedArray(3) 0 3 6 9 12 15 18 21 24 27 30 33 36
Example Thread Data Corruption _multArray _multArray After constructor() 0 1 2 3 4 5 6 7 8 9 10 11 12 Thread 0 calls _seedArray(2); Thread 1 calls _seedArray(3); Thread 2 calls _writeToFile(); 0 1 2 3 4 5 6 7 8 9 10 11 12
Example Thread Data Corruption _multArray _multArray After constructor() 0 1 2 3 4 5 6 7 8 9 10 11 12 Thread 0 calls _seedArray(2); Thread 1 calls _seedArray(3); Thread 2 calls _writeToFile(); 0 3 6 9 12 5 6 7 8 9 10 11 12 Thread 1 runs and gets to here...
Example Thread Data Corruption _multArray _multArray After constructor() 0 1 2 3 4 5 6 7 8 9 10 11 12 Thread 0 calls _seedArray(2); Thread 1 calls _seedArray(3); Thread 2 calls _writeToFile(); 0 2 4 9 12 5 6 7 8 9 10 11 12 Thread 0 runs and gets to here...
Example Thread Data Corruption _multArray _multArray After constructor() 0 1 2 3 4 5 6 7 8 9 10 11 12 Thread 0 calls _seedArray(2); Thread 1 calls _seedArray(3); Thread 2 calls _writeToFile(); 0 2 4 9 12 5 6 7 8 9 10 11 12 Thread 2 runs and gets to here... _myFile: “_multArray=[ 0 2 4 9 12 5 6 “
Example Thread Data Corruption _multArray _multArray After constructor() 0 1 2 3 4 5 6 7 8 9 10 11 12 Thread 0 calls _seedArray(2); Thread 1 calls _seedArray(3); Thread 2 calls _writeToFile(); 0 2 4 6 8 10 12 14 16 18 10 11 12 Thread 0 runs and gets to here... _myFile: “_multArray=[ 0 2 4 9 12 5 6 “
Example Thread Data Corruption _multArray _multArray After constructor() 0 1 2 3 4 5 6 7 8 9 10 11 12 Thread 0 calls _seedArray(2); Thread 1 calls _seedArray(3); Thread 2 calls _writeToFile(); 0 2 4 6 8 10 12 14 16 18 10 11 12 Thread 2 runs and gets to here... _myFile: “_multArray=[ 0 2 4 9 12 5 6 14 16 18 10 11 “
Example Thread Data Corruption _multArray _multArray After constructor() 0 1 2 3 4 5 6 7 8 9 10 11 12 Thread 0 calls _seedArray(2); Thread 1 calls _seedArray(3); Thread 2 calls _writeToFile(); 0 2 4 6 8 15 18 21 24 27 30 33 36 Thread 1 runs and gets to here... _myFile: “_multArray=[ 0 2 4 9 12 5 6 14 16 18 10 11 “
Example Thread Data Corruption _multArray _multArray After constructor() 0 1 2 3 4 5 6 7 8 9 10 11 12 Thread 0 calls _seedArray(2); Thread 1 calls _seedArray(3); Thread 2 calls _writeToFile(); 0 2 4 6 8 15 18 21 24 27 30 33 36 Thread 2 completes... _myFile: “_multArray=[ 0 2 4 9 12 5 6 14 16 18 10 11 36]“
Synchronization • Problem is that you can’t control when/how long each thread runs • What you can do is ensure that the threads don’t work with the same data at the same time • Defn: Critical section -- one or more pieces of code that should not be invoked by >1 thread simultaneously • Defn: Mutual exclusion -- only one thread can be executing this block at a time • Defn: Lock -- data struct used to ensure mutual exclusion w/in critical sections
Synchronization in Java • Java provides synchronized keyword • synchronized method: only one thread can execute in this method at a time • synchronized block: only one thread in this block at a time • Synchronization uses (invisible) lock assoc. w/ object • Normal method -- the invoking object • Static method -- the global “class” obj • Block -- the argument obj to that block