310 likes | 436 Views
A Simple Function. double balance; // a global variable void transaction (double amount, boolean deposit) { if (deposit) balance = balance + amount; else balance = balance - amount; }. A Concurrent World. Employee Automatic Deposit. ATM Withdrawal. transaction (200, false).
E N D
A Simple Function double balance; // a global variable void transaction (double amount, boolean deposit){ if (deposit) balance = balance + amount; else balance = balance - amount;}
A Concurrent World Employee Automatic Deposit ATM Withdrawal transaction (200, false) transaction (1500, true) double balance; // a global variable void transaction (double amount, boolean deposit){ if (deposit) balance = balance + amount; else balance = balance - amount;}
The UML View: A Sequence Diagram Employee Automatic Deposit handler ATM Withdrawal handler Bank Employer Payroll Program ATM user request balance = 2000 transaction (1500, true) handle transaction balance = 3500 transaction (200, false) handle transaction balance = 3300
Alternate Scenario: Withdraw First Employee Automatic Deposit handler ATM Withdrawal handler Bank Employer Payroll Program balance = 2000 ATM user request transaction (200, false) handle transaction balance = 1800 transaction (1500, true) handle transaction balance = 3300
Alternate Scenario: Simultaneously Employee Automatic Deposit handler ATM Withdrawal handler Bank Employer Payroll Program balance = 2000 ATM user request transaction (1500, true) transaction (200, false) handle transaction handle transaction balance = ?
Concurrency Concepts • Single-threaded versus multi-threaded • Process versus thread • The state of a program • data related to current execution of a program • this data is distinct from a separate execution • state of threads, processes, machines • Atomic actions, interleaving, history • one atomic action != one line of code • concurrency allows histories to interleave
UML View#2: An Activity Diagram Listen for transaction calls Receive transaction call Handle transaction call
Finding Patterns in a File(Goal: Make Concurrent Version) string line; read a line of input from source into line; while (not end of file) { look for pattern in line; if (pattern in line) write line; read next line of input; }
How to Parallelize? • Identify where aspects are independent • Look for independent tasks • Look for independent data • Consider read and write sets • Choose level of granularity • Coarse-grain for a few processors/nodes • Fine-grain for many processors/nodes • Types of tasks, volume of data are factors x = (w + p) * (m + q); z = x + 23; p = p / 2;
Concurrency Sub-Goals • Efficiency (avoid useless waiting) • Do parts of the work in parallel • Safety (avoid interference) • Do enforce consistent view for each worker • Liveness (avoid starvation) • Do allow each worker to do its work • Applicability (avoid split if high overhead) • Do split work/data only when it helps
Finding Patterns (Version 2) // plan: split reading and searching tasks string line; read a line of input from source into line; while (not end of file) { [thread#1] { look for pattern in line; if (pattern in line) write line; } [thread#2] { read next line of input; } }
Version 2 Evaluation • Efficiency: nobody uselessly waiting • Safety: line can get trampled • Liveness: • Applicability:
Finding Patterns (Version 3) // plan: fix line from being trampled string line1, line2; read a line of input from source into line2; while (not end of file) { [thread#1] { look for pattern in line1; if (pattern in line) write line1; } [thread#2] { read next line of input into line2; } }
Version 3 Evaluation • Efficiency: nobody uselessly waiting • Safety: nobody’s data gets trampled • Liveness: nobody waiting forever • Applicability: lines never shared at all!
Finding Patterns (Version 4) // plan: make sure both use same data string line1, line2; read a line of input from source into line1; while (not end of file) { [thread#1] { look for pattern in line1; if (pattern in line) write line1; } [thread#2] { read next line of input into line2; } line1 = line2; }
Version 4 Evaluation • Efficiency: nobody uselessly waiting * • Safety: nobody’s data gets trampled • Liveness: nobody waiting forever • Applicability: processes/threads created every iteration *Minor problem: everybody waits for last line of code in loop
Finding Patterns (Version 5) string buffer; // assume “empty” at beginning bool done = false; [thread#1] { string line1; while (true) { wait for done or buffer to be full; if (done) break; line1 = buffer; signal that buffer is empty; look for pattern in line1; if (pattern is in line1) write line1; } }[thread#2] { string line2; while (true) { read next line of input into line2; if (end of file) { done = true; break; } wait for buffer to be empty; buffer = line2; signal that buffer is full; } }
Version 5 Evaluation • Efficiency: nobody uselessly waiting • Safety: nobody’s data gets trampled • Liveness: nobody waiting forever • Applicability: splits applied appropriately
Some Key Points • Create processes/threads as little as possible • thus, version 5 better than version 4 • A simple producer/consumer pattern • producer: file reader • consumer: pattern searcher • Be careful how the two are synchronized • problem: line-by-line lock-step • better: allow each to run at their own pace
Finding Max of an Array // assume an array (int a[n]) int m = 0; for [i = 0 to n - 1] { if (a[i] > m) m = a[i]; }
Finding Max (Version 2) int m = 0; thread [i = 0 to n - 1] { if (a[i] > m) m = a[i]; }
Finding Max (Version 3) int m = 0; thread [i = 0 to n - 1] { [exclusive lock m] if (a[i] > m) m = a[i]; [unlock m] }
Finding Max (Version 4) int m = 0; thread [i = 0 to n - 1] { if (a[i] > m) { [exclusive lock m] m = a[i]; [unlock m] } }
Finding Max (Version 5) int m = 0; thread [i = 0 to n - 1] { if (a[i] > m) { [exclusive lock m] if (a[i] > m) m = a[i]; [unlock m] } }
More Key Points • Enter critical sections as little as possible • version 5 may prevent lots from entering • Sometimes there’s only so much that is independent (oh well) • Be very wary of dangerous histories
An Example of Interleaving int y = 0, z = 0; [thread#1] { x = y + z; } [thread#2] { y = 1; z = 2; }
Interleaving Example #2 int x = 0, y = 0; [thread#1] { x = x + 1; } [thread#2] { y = y + 1; }
Interleaving Example #3 int x = 0, y = 0; [thread#1] { x = y + 1; } [thread#2] { y = y + 1; }
Interleaving Example #4 int x = 0, y = 0; [thread#1] { x = y + 1; } [thread#2] { y = x + 1; }
Interleaving Example #5 int m = 3, p = 14, q = 7, r = 10; [thread#1] { m = p + r; } [thread#2] { q = q + 1; } [thread#3] { r = m + 1; } [wait for threads to finish] p = p + 3; r = r + 1;
How to Program Multithreading? • Need a way to create and manage threads • e.g. a “thread” command • Need a way to lock access to variables • e.g. “lock” and “unlock” commands • real need is for “test and set” capability • Need a way to communicate conditions • e.g. “wait” and “signal” commands