Title: Web Programming Course
 1Web Programming Course
- Lecture 5  Concurrent Programming 2
2Why Synchronization?
- public class Stack 
-  
-  int top0 
-  int data  new int10 
-  public void push(int num) 
-   
-  datatopnum 
-  top  top  1 
-   
-  
-  public int pop() 
-   
-  top  top - 1 
-  return datatop 
-   
3Why Synchronization?
- push() consists of 2 operations 
- store the element into datatop 
- increment top 
- If push() was started, it is supposed to be 
 completed with no interrupts.
- Consider the following example of two threads 
 using push() method
4Why Synchronization?
- class PushThread extends Thread  
-  Stack stack 
-  
-  PushThread(Stack stack, String name)  
-  super(name) 
-  this.stackstack 
-   
-  public void run()  
-  int number 
-  while (true)  
-  number(int)(Math.random()100)  1 
-  while (stack.isFull())  
-  stack.push(number) 
-   
-   
5Why Synchronization?
- class PopThread extends Thread  
-  Stack stack 
-  
-  PopThread(Stack stack, String name)  
-  super(name) 
-  this.stackstack 
-   
-  public void run()  
-  int result 
-  while (true)  
-  while (stack.isEmpty())  
-  result  stack.pop() 
-   
-   
6Why Synchronization?
- public class StackDemo  
-  public static void main(String args)  
-  Stack stack  new Stack() 
-  Thread push1new PushThread(stack,"push1_Thread"
 )
-  Thread push2new PushThread(stack,"push2_Thread"
 )
-  
-  push1.start() 
-  push2.start() 
-  pop1.start() 
-  pop2.start() 
-   
-  
7Why Synchronization?
top
- Consider a scenario 
- Initially, the stack is empty, i.e., top0 
- push1 calls to stack.push(1) 
- push2 calls to stack.push(2) 
- push1 performs data01 //top0 
- push2 performs data02 //top0 
- push1 performs top //top1 
- push2 performs top //top2
3
2
1
0 
 8Race Condition
- Race condition The situation where several 
 processes access and manipulate shared data (or
 resource memory, file, stream) concurrently.
- The final value of the shared data depends upon 
 which process finishes last.
- To prevent race conditions, concurrent processes 
 must be synchronized.
9The Critical-Section Problem
- n running processes are competing to use the same 
 shared data.
- Each process has a code segment, called critical 
 section, in which the shared data is accessed.
- Problem  ensure that when one process is 
 executing its critical section, no other process
 is allowed to execute its critical section.
10Critical-Section Problem
- Mutual exclusion - If a process Pi is executing 
 its CS, no other processes can be executing their
 CS.
- Progress - If no process is executing its CS and 
 there exist some processes that wish to enter
 their CS, then their enter will not be postponed
 indefinitely.
- Bounded Waiting - A bound must exist on the 
 number of times that other processes are allowed
 to enter their CS after a process has made a
 request to enter its CS and before that request
 is granted.
11Critical Sections 
 12Critical Sections
- Execution of the critical section will require 
 atomicity
- Execution by one thread only 
- Either does not start or fully completes 
- If the execution has started, it will be 
 completed
- No interruptions
13Critical Sections
- Synchronization Methods 
- Locks 
- Semaphores 
- Monitors 
- Synchronization Problems 
- Producer-Consumer Problem 
- Bounded Buffer Problem 
- Readers-Writers Problem
14Synchronization  attempt 1
-  Process A 
 Process B
-  ... ... 
-  while( TRUE )  while( TRUE )  
-  ... ... 
-  while( o.proc  B ) while( o.proc  
 A )
-  lt criticalA gt lt criticalB gt 
-  o.proc  B o.proc  A 
-  ... ... 
-    
-  ... ... 
- Problem violates rule 2 (strict alteration).
15Synchronization  attempt 2
-  Process A Process B 
-  ... ... 
-  while( TRUE )  while( TRUE )  
-  ... ... 
-  while( o.pBinside ) while( o.pAinside 
 )
-  o.pAinside  TRUE o.pBinside  TRUE 
-  lt criticalA gt lt criticalB gt 
-  o.pAinside  FALSE o.pBinside  
 FALSE
-  ... ... 
-    
-  ... ... 
- Problem violates rule 1 (interleaved 
 instructions).
16Hardware Solution
- Synchronization solutions are based on hardware 
 level operations
- Many CPUs support atomic read-modify-write 
 operations
- TAS  test-and-set (Motorola 68K) 
- CAS  compare-and-swap (IBM 370 and Motorola 68K) 
- XCHG  exchange (x86)
17Hardware Solution
- Example using test-and-set (TAS)
18Semaphores
- A semaphore is a synchronization variable that 
 takes on non-negative integers with two atomic
 operations
-  P()  while ( semaphore lt 0 ) 
-  //wait()  
-  semaphore--  
-  V()  semaphore 
-  //signal()  
-  
- Semaphores are simple, yet elegant, and allow the 
 solution of many problems. They are useful for
 more than just mutual exclusion.
19Object-Oriented Semaphore
- class Semaphore  
-  private int value 
-  
-  //initialized with non-negative value 
-  public Semaphore(int val) value  val 
-  
-  public void down()  
-  while (value lt 0 )  
-  value-- 
-   
-  
-  public void up()  
-  value  
-   
20Properties of semaphores
- Semaphores are not provided by hardware, but they 
 have several attractive properties
- Simple. 
- Single resource works with many threads. 
- Can have many different critical sections with 
 different semaphores.
- Each critical section has unique access 
 semaphore.
- Can permit multiple threads into the critical 
 section at once.
21Possible Use of Semaphores
- Mutual exclusion initialize the semaphore to one 
 simultaneous thread in CS.
- init Semaphore mutexnew Semaphore(1) 
-  1 mutex.down() 
-  2 func() 
-  3 mutex.up()
22Type of semaphores
- Semaphores are usually available in two flavors 
- Binary  is a semaphore with an integer value of 
 0 and 1.
- Counting  is a semaphore with an integer value 
 ranging between 0 and an arbitrarily large
 number.
- Its initial value represents the number of units 
 of the critical resources that are available.
- This form is also known as a general semaphore. 
- Semaphore are considered parts of the basic 
 synchronization services.
23Implementation of semaphores
- No existing hardware implements Up() and Down() 
 operations directly.
- Semaphores are built-up in software using 
 elementary hardware synchronization primitives.
- Naïve uni-processor solution disable interrupts. 
24Monitors
- Although semaphores solve synchronization 
 problems, they provide low-level and error-prone
 solutions.
- A better (higher-level) solution is provided by 
 the monitor
- A mutex semaphore is associated with a shared 
 resource and any piece of code that touches these
 variables is preceded by mutex.down() and
 followed by mutex.up().
- Why not to let the compiler to do this work?
25Monitors in Java
- Using the synchronized keyword 
- Synchronization order 
- Gain a monitor (lock) 
- Perform the desired operation 
- Release the monitor 
- Thread can not access the CS without obtaining 
 the lock
26Synchronized Methods
- A synchronized method locks the current object 
 such that no other thread can execute inside the
 object while the method is active.
- By locking the object, we guarantee that its 
 state will remain consistent during the duration
 in which the lock on the object is held by a
 thread.
- When the lock is released, then another thread 
 can lock the object and update its state.
27Synchronized Objects
- Java objects are all lockable objects. 
- Every object in Java is a subtype of the Object 
 class in Java.
- The Object class implements an implicit locking 
 mechanism that allows any object to be locked
 during a synchronized method or synchronized
 block
- This provides mutual exclusion
28Object-Level Synchronization
- public void push(int num) 
-  synchronized(this) 
-  datatopnum 
-  top 
-   
-   
-  public int pop() 
-  synchronized(this) 
-  top-- 
-  return datatop 
-   
-   
29Method-Level Synchronization
- public synchronized void push(int num) 
-  datatopnum 
-  top 
-  
- public synchronized int pop() 
-  top-- 
-  return datatop 
-  
30Java Synchronization Example
t1
t2
t3
synchronized(this)  ... 
Note, that mutual exclusion holds between 
synchronized pieces of code only!!
Object-level synchronization 
 31Method-level or Object-level
- Synchronization decreases parallelization 
- It is preferable to synchronize the critical 
 sections only
- Object-level synchronization 
- However, object-level synchronization is 
 impossible for static methods
- Synchronized static methods of a class can not be 
 executed in parallel
32Synchronization Example
class InternetBankingSystem  public 
static void main(String  args )  
Account accountObject  new Account () 
 Thread t1  new Thread(new MyThread(accountObje
ct)) Thread t2  new Thread(new 
YourThread(accountObject)) Thread t3  new 
Thread(new HerThread(accountObject)) 
t1.start() t2.start() 
t3.start() // do some other operation 
  // end main()  
 33Synchronization Example
class MyThread implements Runnable  Account 
account public MyThread (Account s)  
account  s public void run()  
account.deposit()   // end class 
MyThread class YourThread implements Runnable 
 Account account public YourThread 
(Account s)  account  s public void 
run()  account.withdraw()   // end class 
YourThread class HerThread implements Runnable 
 Account account public HerThread 
(Account s)  account  s  public void 
run() account.enquire()   // end class 
HerThread
account (shared object) 
 34Synchronization Example
- class Account  // the 'monitor' 
-  int balance 
- // if 'synchronized' is removed, the outcome is 
 unpredictable
-  public synchronized void deposit( )  
-  // METHOD BODY  balance  deposit_amount 
-   
-  public synchronized void withdraw( )  
-  // METHOD BODY balance - deposit_amount 
-   
-  public synchronized void enquire( )  
-  // METHOD BODY display balance. 
-   
35Synchronization Example
- 3 methods f1(), f2() and f3() in MyClass 
- Neither 2 instances of f1() nor 2 instances of 
 f2() can be executed in parallel
- However, defining them as synchronized will not 
 allow to execute f1() in parallel with f2()
36Synchronization Example
- Solution defining 2 different monitors 
- private static Object sync_f1  new Object() 
- private static Object sync_f2  new Object() 
- And synchronizing on these monitors 
- void f1()  
-  synchronized (sync_f1)  
-  ... // code of f1() 
-   
-  
- void f2()  
-  synchronized (sync_f2)  
-  ... // code of f2() 
-   
37Synchronization Example
- f3() can not be executed in parallel neither with 
 f1() nor with f2()
- Solution 
- void f3()  
-  synchronized (sync_f1)  
-  synchronized (sync_f2)  
-  ...// code of f3() 
-   
-   
38Wait(), Notify(), and NotifyAll()
- Synchronized methods are methods that lock the 
 object on entry and unlock the object on exit.
- The Object class implements some special methods 
 for allowing a thread to
- explicitly release the lock while in the method 
- wait for the lock for some time 
- notify other threads
39Wait(), Notify(), and NotifyAll()
- wait() causes a thread to wait (indefinitely or 
 for some time interval), and then try to
 reacquire the lock
- notify() signals one (defined at the run-time) 
 thread to wakeup
- notifyAll() signals all threads to wakeup and 
 compete to re-acquire the lock
- If no thread is waiting, then notify() and 
 notifyAll() have no effect
40Wait(), Notify(), and NotifyAll()
- These methods should be used only from within 
 methods holding the object lock
- If called without holding the lock, the 
 IllegalMonitorStateException is thrown
- A waiting (or sleeping) thread can also be awoken 
 if it is interrupted by another thread
- In this case, the InterruptedException is thrown
41Producer-Consumer Problem
- Correct behavior is 
- Producer puts 1 value in buffer 
- Then Consumer reads it 
- And so on 
- If no concurrency control on Buffer 
- If Producer is quicker than Consumer, Consumer 
 will skip 1 or more values
- Vice versa, Consumer will read same values 2 or 
 more times
- Need to synchronize the work of Producer and 
 Consumer
42Producer-Consumer Example
- class Producer extends Thread  
-  private Buffer buf 
-  private int number // id 
-  public Producer(Buffer b, int n) 
-  buf  b number  n 
-  public void run()  
-  for (int i  0 i lt 10 i)  
-  buf.put(i) 
-  System.out.println( 
-  "Producer "  number  
-  " put "  i) 
-  //random sleep ... 
-   
-   
- class Consumer extends Thread  
-  private Buffer buf 
-  private int number // id 
-  public Consumer(Buffer b, int n) 
-  buf  b number  n 
-  public void run()  
-  int value  0 
-  for (int i  0 i lt 10 i)  
-  value  buf.get() 
-  System.out.println( 
-  "Consumer "  number  
-  " got "  value) 
-   
-   
43Expected Output
- Producer 1 put 0 
- Consumer 1 got 0 
- Producer 1 put 1 
- Consumer 1 got 1 
- Producer 1 put 2 
- Consumer 1 got 2 
- Producer 1 put 3 
- Consumer 1 got 3 
- Producer 1 put 4 
- Consumer 1 got 4 
-  
- Producer 1 put 5 
- Consumer 1 got 5 
- Producer 1 put 6 
- Consumer 1 got 6 
- Producer 1 put 7 
- Consumer 1 got 7 
- Producer 1 put 8 
- Consumer 1 got 8 
- Producer 1 put 9 
- Consumer 1 got 9 
44Synchronized Produce-Consumer 
- class Buffer  
-  //shared resource 
-  private int num  -1 //invalid 
-  
-  public synchronized int get()  
-  return num 
-   
-  public synchronized void put(int value) 
-  num  value 
-   
45Synchronized Produce-Consumer
- public class ProducerConsumerTest  
-  public static void main()  
-  Buffer b  new Buffer() 
-  Producer p1new Producer(b, 1) 
-  Consumer c1new Consumer(b, 1) 
-  p1.start() 
-  c1.start() 
-   
46Does it work?
- Synchronized ensures only that 
- put() and get() cannot be invoked at exactly the 
 same time (no overwriting while reading)
- In case there are multiple producers and/or 
 consumers, they queue up nicely
- It does not ensure alternation 
- e.g. Consider a case in which Consumer calls 
 get() before Producer had a chance to call put()
- One or more times 
- We need some device for threads explicitly 
 coordinating with each other!
47Synchronized Produce-Consumer
- public synchronized void consume()  
-  while (!consumable())  
-  wait() // release lock and wait for resource 
-   
-  ... //have exclusive access to resource to 
 consume
-  
- public synchronized void produce()  
-  ... //change of state must result in consumable 
 condition being true
-  notifyAll() // notify all waiting threads to 
 try consuming
48Synchronized Produce-Consumer
- class Buffer  
- private int num 
-  private boolean availablefalse 
-  public synchronized int get()  
-  while (available  false)  
-  try this.wait() 
-  catch(InterruptedException e)e.printStackTrac
 e()
-   
-  available  false 
-  this.notifyAll() 
-  return num 
-   
-  public synchronized void put(int value) 
-  while (available  true) 
-  try  this.wait() 
-  catch(InterruptedException e)e.printStackTrac
 e()
-   
-  num  value 
-  available  true 
49Condition Variables
- When a thread is awoken, it cannot assume that 
 its condition is true, as all threads are
 potentially awoken by notifyAll()
- One would expect that the thread can assume that 
 when it awakes, the shared resource is in the
 appropriate state
- This is not always the case
50Condition Variables
- Another thread could get access to the shared 
 resource and modify it
- When the thread eventually gains access to the 
 lock, the shared resource can again be
 inaccessible
- Hence, it is usually essential for threads to 
 re-evaluate their guards
51Bounded Buffer Example
public class BoundedBuffer  private int 
buffer private int first private int 
last private int numberInBuffer  0 private 
int size public BoundedBuffer(int length)  
 size  length buffer  new intsize 
last  0 first  0  
 52Bounded Buffer Example
 public synchronized void put(int item) 
 throws InterruptedException  while 
(numberInBuffer  size) wait() last  
(last  1)  size  //   modulus 
numberInBuffer bufferlast  item 
 notifyAll()  public synchronized int 
get() throws InterruptedException  
 while (numberInBuffer  0) wait() first 
 (first  1)  size  //   modulus 
numberInBuffer-- notifyAll() return 
bufferfirst   
 53Readers-Writers Problem
- Many reader and writer threads are attempting to 
 access an object storing a large data structure
- Readers can read concurrently, as they do not 
 alter the data
- Writers require mutual exclusion over the data 
 both from other writers and from readers
- Priority is always given to waiting writers 
- As soon as a writer is available, all new readers 
 will be blocked until all writers have finished
54Readers-Writers Problem
- Standard solution requires 4 monitor methods, 
 which are used
startRead() // call object to read data 
structure stopRead() 
startWrite() // call object to write data 
structure stopWrite()  
 55Readers-Writers Problem
- Standard solution in monitors is to have two 
 condition variables OkToRead and OkToWrite
- This cannot be directly expressed using a single 
 Java monitor
public class ReadersWriters  private int 
readers  0 private int waitingWriters  0 
private boolean writing  false  
 56Readers-Writers Problem
 public synchronized void StartWrite()  
while(readers gt 0  writing)  
waitingWriters wait() 
waitingWriters--  writing  true  
 public synchronized void StopWrite()  
writing  false notifyAll()  
loop to re-test the condition
Wakeup everyone 
 57Readers-Writers Problem
 public synchronized void StartRead() 
throws InterruptedException  while(writing 
 waitingWriters gt 0) wait() readers 
 public synchronized void StopRead()  
readers-- if(readers  0) notifyAll()   
 58Starvation and Deadlock
- Starvation  situation where a thread is 
 continuously deferred by the scheduler
- Deadlock  situation two or more threads can not 
 proceed, since they are waiting for each other
59Deadlock Necessary Conditions
- Mutual Exclusion 
- Each processor has exclusive use of its resources 
- Non-preemption 
- A process never releases resources until it has 
 finished using them
- Resource waiting 
- Each process holds resources while waiting for 
 other processes to release theirs
- Cycle of waiting processes 
- Each process in the cycle waits for resources 
 that the next process owns and will not relinquish
60(No Transcript) 
 61Dining Philosophers Problem
- A philosopher can 
- Think 
- Gives up the two chopsticks on right and left 
- Eat 
- Picks up the two chopsticks on right and left one 
 at a time
- If chopstick is in use, must wait until neighbor 
 thinks and then picks it up
62Dining Philosophers Problem
- Deadlock Scenario 
- Philosopher 1 takes his right chopstick 
- Philosopher 2 takes his right chopstick 
- Philosopher 3 takes his right chopstick 
-  
- What are the deadlock conditions in this scenario?