“Summationjob” Race Conditions Example – a Lucky Scenario

“Summationjob” Race Conditions Example – a Lucky Scenario

11/25/14 Race Conditions 2 ¨ A “race condition” arises if two or more threads access the same variables or objects concurrently and at least one does updates ¨ Example: Suppose t1 and t2 simulatenously execute the statement x = x + 1; for some static global x. ¤ Internally, this involves loading x, adding 1, storing x ¤ If t1 and t2 do this concurrently, we execute the RACE CONDITIONS AND statement twice, but x may only be incremented once SYNCHRONIZATION ¤ t1 and t2 “race” to do the update Lecture 25 – CS2110 – Fall 2014 Race Conditions Working Example: “SummationJob” 3 4 public class SummationJob implements Runnable {! ! ¨ Suppose X is initially 5 public static int X = 0;! public static int NDONE = 0;! public static final int NTHREADS = 2;! ! /** Increments X 1000 times. */! Thread t1 Thread t2 public void run() {! for(int k=0; k<1000; k++) {! X = X + 1; // (WARNING: MAIN RACE CONDITION)! }! NDONE += 1; // (WARNING: ANOTHER RACE CONDITION)! ¨ ¨ }! LOAD X ... ! /** Launches NTHREADS SummationJob objects that try to increment X to NTHREADS*1000 */! public static void main(String[] args) {! ¨ try {! LOAD X Thread[] threads = new Thread[NTHREADS];! for(int k=0; k<NTHREADS; k++) ! threads[k] = new Thread(new SummationJob());! ¨ ADD 1 ¨ ADD 1 ! for(int k=0; k<NTHREADS; k++) ! threads[k].start();! ! ¨ STORE X while(NDONE < NTHREADS) Thread.sleep(100);! ! System.out.println("X="+X);! ! ¨ STORE X }catch(Exception e) {! e.printStackTrace();! System.out.println("OOPS"+e);! }! }! ¨ ... after finishing, X=6! We “lost” an update }! Race Conditions Example – A Lucky Scenario 5 6 private Stack<String> stack = new Stack<String>(); ¨ Race conditions are bad news public void doSomething() { ¤ Sometimes you can make code behave correctly if (stack.isEmpty()) return; despite race conditions, but more often they cause bugs String s = stack.pop(); //do something with s... } ¤ And they can cause many kinds of bugs, not just the Suppose threads A and B want to call doSomething(), example we see here! and there is one element on the stack 1. thread A tests false ¤ A common cause for “blue screens”, null pointer stack.isEmpty() ⇒ exceptions, damaged data structures 2. thread A pops stack is now empty 3. thread B tests stack.isEmpty() ⇒ true 4. thread B just returns – nothing to do 1 11/25/14 Example – An Unlucky Scenario Synchronization 7 8 private Stack<String> stack = new Stack<String>(); ¨ Java has one “primary” tool for preventing these public void doSomething() { if (stack.isEmpty()) return; problems, and you must use it by carefully and String s = stack.pop(); explicitly – it isn’t automatic. //do something with s... } ¤ Called a “synchronization barrier” Suppose threads A and B want to call doSomething(), ¤ We think of it as a kind of lock and there is one element on the stack n Even if several threads try to acquire the lock at once, only one can succeed at a time, while others wait 1. thread A tests stack.isEmpty() ⇒ false n When it releases the lock, the next thread can acquire it 2. thread B tests stack.isEmpty() ⇒ false n You can’t predict the order in which contending threads will 3. thread A pops ⇒ stack is now empty get the lock but it should be “fair” if priorities are the same 4. thread B pops ⇒ Exception! Solution – with synchronization Solution – Locking 9 10 private Stack<String> stack = new Stack<String>(); • You can lock on any object, including this public void doSomething() { synchronized (stack) { if (stack.isEmpty()) return; public synchronized void doSomething() { String s = stack.pop(); ... } } //do something with s... } synchronized block is equivalent to public void doSomething() { synchronized (this) { ... • Put critical operations in a synchronized block } • The stack object acts as a lock } • Only one thread can own the lock at a time How locking works Locks are associated with objects 11 12 ¨ Only one thread can “hold” a lock at a time ¨ Every Object has its own built-in lock ¤ If several request the same lock, Java somehow decides ¤ Just the same, some applications prefer to create which will get it special classes of objects to use just for locking ¨ The lock is released when the thread leaves the ¤ This is a stylistic decision and you should agree on it synchronization block with your teammates or learn the company policy if you work at a company ¤ synchronized(someObject) { protected code } ¨ ¤ The protected code has a mutual exclusion guarantee: Code is “thread safe” if it can handle multiple At most one thread can be in it threads using it… otherwise it is “unsafe” ¨ When released, some other thread can acquire the lock 2 11/25/14 Working Example: “SummationJob” Synchronization+priorities 13 14 public class SummationJob implements Runnable {! ! public static int X = 0;! ¨ Combining mundane features can get you in trouble public static int NDONE = 0;! How can we use locks to public static final int NTHREADS = 2;! ! /** Increments X 1000 times. */! update results? ¨ Java has priorities... and synchronization public void run() {! for(int k=0; k<1000; k++) {! (keeping silly +1 computation). X = X + 1; // (WARNING: MAIN RACE CONDITION)! ¤ But they don’t “mix” nicely }! NDONE += 1; // (WARNING: ANOTHER RACE CONDITION)! }! ! ¤ High-priority runs before low priority /** Launches NTHREADS SummationJob objects that try to increment X to NTHREADS*1000 */! public static void main(String[] args) {! try {! ¤ ... The lower priority thread “starves” Thread[] threads = new Thread[NTHREADS];! for(int k=0; k<NTHREADS; k++) ! threads[k] = new Thread(new SummationJob());! ! ¨ Even worse... for(int k=0; k<NTHREADS; k++) ! threads[k].start();! ! ¤ With many threads, you could have a second high while(NDONE < NTHREADS) Thread.sleep(100);! ! System.out.println("X="+X);! priority thread stuck waiting on that starving low ! }catch(Exception e) {! e.printStackTrace();! priority thread! Now both are starving... System.out.println("OOPS"+e);! }! }! }! Fancier forms of locking Finer grained synchronization 15 16 ¨ Java developers have created various ¨ Java allows you to do fancier synchronization synchronization ADTs ¤ But can only be used inside a synchronization block ¤ Semaphores: a kind of synchronized counter ¤ Special primitives called wait/notify ¤ Event-driven synchronization n In java.lang.Object ¨ The Windows and Linux and Apple O/S all have kernel locking features, like file locking ¨ But for Java, synchronized is the core mechanism java.lang.Object wait/notify 18 Suppose we put this inside an object called animator: boolean isRunning = true; public synchronized void run() { must be synchronized! while (true) { while (isRunning) { //do one step of simulation } relinquishes lock on animator – try { awaits notification wait(); } catch (InterruptedException ie) {} isRunning = true; public void stopAnimation() { } animator.isRunning = false; } } public void restartAnimation() { notifies processes waiting synchronized(animator) { for animator lock animator.notify(); } 17 } 3 11/25/14 Deadlock Visualizing deadlock 19 20 ¨ The downside of locking – deadlock A has a lock on X wants a lock on Y ¨ A deadlock occurs when two or more competing threads are waiting for one-another... forever Process Process A X B Y ¨ Example: ¤ Thread t1 calls synchronized b inside synchronized a B has a lock on Y wants a lock on X ¤ But thread t2 calls synchronized a inside synchronized b ¤ t1 waits for t2... and t2 waits for t1... Deadlocks always involve cycles Dealing with deadlocks 21 22 ¨ They can include 2 or more threads or processes in ¨ We recommend designing code to either a waiting cycle ¤ Acquire a lock, use it, then promptly release it, or ¨ Other properties: ¤ ... acquire locks in some “fixed” order ¤ The locks need to be mutually exclusive (no sharing of the objects being locked) ¨ Example, suppose that we have objects a, b, c, ... ¤ The application won’t give up and go away (no timer ¨ Now suppose that threads sometimes lock sets of associated with the lock request) objects but always do so in alphabetical order ¤ There are no mechanisms for one thread to take locked ¤ Can a lock-wait cycle arise? resources away from another thread – no “preemption” ¤ ... without cycles, no deadlocks can occur! “... drop that mouse or you’ll be down to 8 lives” Higher level abstractions A producer/consumer example 23 24 ¨ Locking is a very low-level way to deal with ¨ Thread A produces loaves of bread and puts them synchronization on a shelf with capacity K ¤ Very nuts-and-bolts ¤ For example, maybe K=10 ¨ Thread B consumes the loaves by taking them off ¨ So many programmers work with higher level the shelf concepts. Sort of like ADTs for synchronization ¤ Thread A doesn’t want to overload the shelf ¤ We’ll just look at one example today ¤ Thread B doesn’t wait to leave with empty arms ¤ There are many others; take CS4410 “Operating Systems” to learn more producer shelves consumer 4 11/25/14 Producer/Consumer example Things to notice 25 26 ¨ class Bakery { Wait needs to wait on the same object that you int nLoaves = 0; // Current number of waiting loaves used for synchronizing (in our example, “this”, which final int K = 10; // Shelf capacity is this instance of the Bakery) public synchronized void produce() { while(nLoaves == K) this.wait(); // Wait until not full ++nLoaves; this.notifyall(); // Signal: shelf not empty ¨ } Notify wakes up just one waiting thread, notifyall wakes all of them up public synchronized void consume() { while(nLoaves == 0) this.wait(); // Wait until not empty --nLoaves; this.notifyall(); // Signal: shelf not full } ¨ We used

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    7 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us