at-m42:lecture9
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
at-m42:lecture9 [2009/04/15 16:29] – eechris | at-m42:lecture9 [2011/01/14 12:45] (current) – external edit 127.0.0.1 | ||
---|---|---|---|
Line 334: | Line 334: | ||
===== Object Locks ===== | ===== Object Locks ===== | ||
- | One lock per object for object’s data members | ||
- | One lock per class for class’ static data members | ||
- | Typically data is private, only accessed through methods | ||
- | If a method is synchronized, | ||
- | No other thread may call that method until the lock is released | ||
- | How Java Shares Resources | ||
- | Only one synchronized method can be called at any time for a particular object synchronized void f() { /* ... */ } synchronized void g(){ /* ... */ } | ||
- | synchronized efficiency | ||
- | Each object has a lock | ||
- | Typical 6x method call overhead, theoretical min 4x | ||
- | Standard Java libraries use synchronized a lot, don’t provide you with alternatives | ||
- | Synchronization efficiency much improved in Java 1.3 and 1.4 | ||
- | The "Lost Update" | ||
- | Occurs when a two-step (or more-step) process is accessed by another thread before it completes. | ||
- | E.g. | ||
- | public void increment(){ int i = balance; | ||
- | Thread A Runs for a While | ||
- | Put the value of balance into variable i. | ||
- | Balance is 0, so i is now 0. | ||
- | Set the balance to the result of i + 1. | ||
- | Now balance is 1. | ||
- | Put the value of balance into variable i. | ||
- | Balance is 1, so i is now 1. | ||
- | Set the balance to the result of i + 1. | ||
- | Now balance is 2. | ||
- | Thread B Runs for a While | + | * One lock per object |
- | Put the value of balance into variable i. | + | * One lock per class for class' '' |
- | Balance | + | * Typically data is '' |
- | Set the balance to the result of i + 1. | + | * If a method |
- | Now balance | + | * No other thread may call that method until the lock is released |
- | Put the value of balance into variable i. | + | |
- | Balance is 3, so i is now 3. | + | |
- | Thread A Runs again | + | |
- | Picking up where it left off | + | |
- | Put the value of balance into variable i. | + | |
- | Balance is 3, so i is now 3. | + | |
- | Set the balance to the result of i + 1. | + | |
- | Now balance is 4. | + | |
- | Put the value of balance into variable i. | + | |
- | Balance is 4, so i is now 4. | + | |
- | Set the balance to the result of i + 1. | + | |
- | Now balance | + | |
- | Thread B runs gain | + | ===== How JVM Shares Resources ===== |
- | And picks up exactly where it left off | + | |
- | Set the balance to the result of i + 1. | + | |
- | Now balance is 4 !!!!. | + | |
- | Make increment atomic | + | |
- | public synchronized void increment(){ | + | |
- | Thread A Runs for a While | + | |
- | Attempt to enter increment method. | + | |
- | Synchronized code, so get the key for this object. | + | |
- | Put the value of balance into variable i. | + | |
- | Balance is 0, so i is now 0. | + | |
- | Set the balance to the result of i + 1. | + | |
- | Now balance is 1. | + | |
- | Return the key | + | |
- | Reenter increment method. Get the key. | + | |
- | Put the value of balance into variable i. | + | |
- | Balance is 1, so i is now 1. | + | |
- | Thread B is selected to run | + | * Only one '' |
- | Attempt to enter increment | + | <code groovy> |
- | The method is synchronized | + | synchronized |
- | The key is not available | + | synchronized g(){ /* ... */ } |
- | Thread B is " | + | </ |
- | Thread A Runs again | + | * '' |
- | Picking up where it left off | + | * Each object has a lock |
- | Set the balance to the result of i + 1. | + | * Typical 6x method call overhead, theoretical minimum 4x |
- | Now balance is 2. | + | |
- | Return the key | + | |
- | Thread B is selected to run | + | ===== The "Lost Update" |
- | Attempt to enter increment method. | + | * Occurs when a two-step (or more-step) process |
- | The method is synchronized so we need to get the key. | + | * E.g. |
- | The key is available, get the key | + | <code groovy> |
- | Put the value of balance into variable i. | + | def increment(){ |
- | Balance is 2, so i is now 2. | + | i = balance; |
- | Set the balance | + | balance |
- | Now balance is 3. | + | } |
- | Return the key | + | </code> |
- | Synchronizing on other resources | + | |
- | Synchronizing on something other than the memory inside an object | + | |
- | Using non-synchronized objects | + | |
- | Best to wrap everything inside an object and guard it with the object’s own synchronized methods, but you can also: | + | |
- | Blocking | + | ---- |
- | Four states of a thread: | + | |
- | 1. New: the thread object has been created but it hasn’t been started yet so it cannot run | + | |
- | 2. Runnable: | + | |
- | 3. Dead: normally after thread returns from its run( ) | + | |
- | 4. Blocked: the thread could be run but there’s something that prevent it. While a thread is in the blocked state the scheduler will simply skip over it and not give it any CPU time | + | |
- | Becoming Blocked | + | |
- | Thread is sleeping: sleep(milliseconds) | + | |
- | Thread is suspended: suspend( ). It will not become runnable again until the thread gets the resume( ) message | + | |
- | Thread is waiting with wait( ). It will not become runnable again until the thread gets the notify( ) or notifyAll( ) message | + | |
- | The thread is waiting for some IO to complete | + | |
- | The thread is trying to call a synchronized method on another object and that object’s lock is not available | + | |
- | Deadlock | + | |
- | A chain of threads waiting on each other, looping back to the beginning | + | |
- | No language support to prevent it | + | |
- | Tough to debug | + | |
- | To create a deadlock only need two threads and two objects | + | |
- | Thread deadlock | + | |
- | Thread deadlock scenario | + | |
- | Thread A enters synchronized method of object foo and gets the key. | + | |
- | Thread A goes to sleep | + | |
- | Thread deadlock scenario | + | |
- | Thread B enters synchronized method of object bar and gets the key. | + | |
- | Thread B tries to enter a synchronized method of object foo, but can't get that key (A has it). | + | |
- | B " | + | |
- | B keeps the bar key. | + | |
- | Thread deadlock scenario | + | |
- | Thread A wakes up and tries to enter a synchronized method on object bar., but can't get that key because B has it. | + | |
- | A " | + | |
- | Thread A can't run until it get's bar key that B is holding. | + | |
- | Thread B can't run until it gets the foo key that A is holding. | + | |
- | Deadlock! | + | |
- | Summary | + | |
- | Single-threaded programming: | + | |
- | Multithreading: | + | |
- | Multithreading makes Java complicated, | + | |
- | Lab Exercises | + | |
- | 1. Inherit a class from Thread and override the run( ) method. Inside run( ), print a message, then call sleep( ). Repeat this 3 times, then return from run( ). Put a start-up message in the constructor and override finalize( ) to print a shut-down message. Make a separate thread class that calls System.gc( ) inside run( ), printing a message as it does so. Make several thread objects of both types and run them to see what happens. | + | |
- | 2. Create two Thread classes, one with a run( ) that starts up, creates and passes its own handle to an object of the second thread class and then calls wait( ). The other classes’ run( ) should cause a notifyAll( ) in the first thread after some number of seconds have passed, so the first thread can print out a message. | + | |
- | {{: | + | Increment '' |
- | ===== Heading 1 ===== | + | ===== Thread A runs for a while ===== |
- | <code groovy 1 | Example 1: Everything | + | {{ : |
- | extern> http://www.cpjobling.org.uk/ | + | |
+ | * '' | ||
+ | - Put the value of '' | ||
+ | - '' | ||
+ | - Set the '' | ||
+ | - Now '' | ||
+ | * '' | ||
+ | - Put the value of '' | ||
+ | - '' | ||
+ | - Set the '' | ||
+ | - Now '' | ||
+ | |||
+ | ===== Thread B runs for a while ===== | ||
+ | |||
+ | {{ :at-m42: | ||
+ | |||
+ | * '' | ||
+ | - Put the value of '' | ||
+ | - '' | ||
+ | - Set the '' | ||
+ | - Now '' | ||
+ | * '' | ||
+ | - Put the value of '' | ||
+ | - '' | ||
+ | |||
+ | ---- | ||
+ | |||
+ | Scheduler now makes '' | ||
+ | Note that this is before '' | ||
+ | |||
+ | ===== Thread A Runs again ====== | ||
+ | |||
+ | {{ :at-m42: | ||
+ | |||
+ | Picking up where it left off: | ||
+ | * '' | ||
+ | - Put the value of '' | ||
+ | - '' | ||
+ | - Set the '' | ||
+ | - Now '' | ||
+ | * '' | ||
+ | - Put the value of '' | ||
+ | - '' | ||
+ | - Set the '' | ||
+ | - Now '' | ||
+ | |||
+ | ===== Thread B runs again ===== | ||
+ | |||
+ | {{ :at-m42: | ||
+ | |||
+ | And picks up //exactly// where it left off: | ||
+ | * Set the '' | ||
+ | * **But balance is //now// 4 !!!!.** | ||
+ | |||
+ | ---- | ||
+ | |||
+ | '' | ||
+ | |||
+ | ===== Make increment atomic ====== | ||
+ | < | ||
+ | synchronized void increment() { | ||
+ | i = balance | ||
+ | balance = i + 1 | ||
+ | } | ||
</ | </ | ||
+ | |||
---- | ---- | ||
- | Notes ... | + | The assignment and increment code will run to end. |
+ | |||
+ | |||
+ | ===== Thread A Runs for a While ===== | ||
+ | {{ : | ||
+ | {{ : | ||
+ | |||
+ | * '' | ||
+ | - '' | ||
+ | - put the value of '' | ||
+ | - '' | ||
+ | - Set the '' | ||
+ | - Now '' | ||
+ | - **Return the key**. | ||
+ | * Thread A re-enters '' | ||
+ | - Put the value of '' | ||
+ | - '' | ||
+ | |||
+ | ===== Thread B is selected to run ===== | ||
+ | |||
+ | {{ : | ||
+ | {{ : | ||
+ | |||
+ | * '' | ||
+ | - The method is '' | ||
+ | - The **key is not available**. | ||
+ | - '' | ||
+ | |||
+ | ===== Thread A Runs again ===== | ||
+ | |||
+ | {{ : | ||
+ | {{ : | ||
+ | * Picking up where it left off | ||
+ | - Set the '' | ||
+ | - Now '' | ||
+ | - **Return the key** | ||
+ | |||
+ | ===== Thread B is selected to run ===== | ||
+ | |||
+ | {{ : | ||
+ | {{ : | ||
+ | |||
+ | * '' | ||
+ | - The method is '' | ||
+ | - The **key is available, get the key** | ||
+ | - Put the value of '' | ||
+ | - Balance is 2, so '' | ||
+ | - Set the '' | ||
+ | - Now '' | ||
+ | - **Return the key** | ||
+ | |||
+ | |||
+ | ===== Synchronizing on other resources ===== | ||
+ | * Synchronizing on something other than the memory inside an object | ||
+ | * Using non-'' | ||
+ | * Best to wrap everything inside an object and guard it with the object' | ||
+ | synchronized(syncObject) { | ||
+ | // This code can only be accessed | ||
+ | // by one thread at a time | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ===== Blocking ===== | ||
+ | |||
+ | Four states of a thread: | ||
+ | - //New//: the thread object has been created but it hasn’t been started yet so it cannot run | ||
+ | - // | ||
+ | - //Dead//: normally after thread returns from its '' | ||
+ | - // | ||
+ | ===== Becoming Blocked ===== | ||
+ | |||
+ | * Thread is // | ||
+ | * Thread is // | ||
+ | * Thread is //waiting// with '' | ||
+ | * The thread is waiting for some I/O to complete. | ||
+ | * The thread is trying to call a '' | ||
+ | |||
+ | ===== Deadlock ===== | ||
+ | |||
+ | * A chain of threads waiting on each other, looping back to the beginning | ||
+ | * No language support to prevent it | ||
+ | * Tough to debug | ||
+ | * To create a deadlock only need two threads and two objects | ||
+ | |||
+ | ===== Thread deadlock ===== | ||
+ | |||
+ | {{: | ||
- | ===== Heading 2 ===== | + | ===== Thread deadlock scenario |
- | * [[#Sub head 1]] | + | {{: |
- | * [[#Sub head 2]] | + | |
+ | * '' | ||
+ | * '' | ||
- | ===== Summary of this Lecture | + | ===== Thread deadlock scenario ===== |
- | + | ||
- | The .... | + | |
+ | {{: | ||
- | * [[#Heading 1]] | + | * '' |
- | * [[#Heading 2]] | + | * '' |
- | * [[#heading 3]] | + | * B " |
+ | * B keeps the '' | ||
- | ===== Lab Exercises | + | ===== Thread deadlock scenario |
+ | {{: | ||
+ | * '' | ||
+ | * A " | ||
+ | * '' | ||
+ | * Thread B can't run until it gets the '' | ||
+ | * **Deadlock!** | ||
- | | + | ===== Summary ===== |
+ | | ||
+ | * Multi-threading: suddenly you can have collisions and destroy information, | ||
+ | * Multi-threading makes programming on the Java Platform complicated. | ||
+ | * Groovy multithreading easier because of the use of the closure. | ||
+ | * **Multi-threading is hard**! | ||
---- | ---- |
at-m42/lecture9.1239812955.txt.gz · Last modified: 2011/01/14 12:26 (external edit)