SlideShare a Scribd company logo
Concurrency and
Synchronisation




                  1
Learning Outcomes
• Understand concurrency is an issue in operating
  systems and multithreaded applications
• Know the concept of a critical region.
• Understand how mutual exclusion of critical
  regions can be used to solve concurrency issues
  – Including how mutual exclusion can be implemented
    correctly and efficiently.
• Be able to identify and solve a producer
  consumer bounded buffer problem.
• Understand and apply standard synchronisation
  primitives to solve synchronisation problems.

                                                    2
Textbook
• Sections 2.3 & 2.5




                          3
Making Single-Threaded Code Multithreaded




Conflicts between threads over the use of a
               global variable            4
Inter- Thread and Process
             Communication



We have a
  race
condition



Two processes want to access shared memory at same
                         time
                                              5
Critical Region
• We can control access to the shared
  resource by controlling access to the code
  that accesses the resource.
⇒ A critical region is a region of code where
  shared resources are accessed.
  – Variables, memory, files, etc…
• Uncoordinated entry to the critical region
  results in a race condition
  ⇒ Incorrect behaviour, deadlock, lost work,…
                                                 6
Critical Regions




Mutual exclusion using critical regions
                                          7
Example critical sections
struct node {                      void insert(struct *item)
   int data;                       {
   struct node *next;                 item->next = head;
};                                    head = item;
struct node *head;                 }

void init(void)                    struct node *remove(void)
{                                  {
   head = NULL;                       struct node *t;
}                                     t = head;
                                      if (t != NULL) {
                                           head = head->next;
• Simple last-in-first-out queue      }
  implemented as a linked list.       return t;
                                   }




                                                                8
Example Race
void insert(struct *item)   void insert(struct *item)
{                           {
   item->next = head;          item->next = head;
   head = item;                head = item;
}                           }




                                                        9
Example critical sections
struct node {           void insert(struct *item)
   int data;            {
   struct node *next;      item->next = head;
};                         head = item;
struct node *head;      }

void init(void)         struct node *remove(void)
{                       {
   head = NULL;            struct node *t;
}                          t = head;
                           if (t != NULL) {
                                head = head->next;
• Critical sections        }
                           return t;
                        }




                                                     10
Critical Regions
Also called critical sections
Conditions required of any solution to the critical region
    problem
    Mutual Exclusion:
       No two processes simultaneously in critical region
    No assumptions made about speeds or numbers of CPUs
    Progress
       No process running outside its critical region may block another
       process
    Bounded
       No process waits forever to enter its critical region




                                                                          11
A solution?
• A lock variable
  – If lock == 1,
     • somebody is in the critical section and we must
       wait
  – If lock == 0,
     • nobody is in the critical section and we are free to
       enter




                                                         12
A solution?
while(TRUE) {           while(TRUE) {
  while(lock == 1);       while(lock == 1);
  lock = 1;               lock = 1;
  critical();             critical();
  lock = 0                lock = 0
  non_critical();         non_critical();
}                       }




                                              13
A problematic execution
               sequence
while(TRUE) {
                        while(TRUE) {
                          while(lock == 1);
    while(lock == 1);
    lock = 1;
                            lock = 1;
    critical();             critical();
    lock = 0
    non_critical();
}                           lock = 0
                            non_critical();
                        }

                                              14
Observation
• Unfortunately, it is usually easier to show
  something does not work, than it is to
  prove that it does work.
  – Ideally, we’d like to prove, or at least
    informally demonstrate, that our solutions
    work.




                                                 15
Mutual Exclusion by Taking Turns




 Proposed solution to critical region problem
(a) Process 0.   (b) Process 1.
                                                16
17
Mutual Exclusion by Taking Turns

• Works due to strict alternation
  – Each process takes turns
• Cons
  – Busy waiting
  – Process must wait its turn even while the other
    process is doing something else.
     • With many processes, must wait for everyone to have a turn
         – Does not guarantee progress if a process no longer needs a
           turn.
     • Poor solution when processes require the critical section at
       differing rates

                                                                    18
Peterson’s Solution
• See the textbook




                              19
Mutual Exclusion by Disabling
           Interrupts
• Before entering a critical region, disable
  interrupts
• After leaving the critical region, enable interrupts
• Pros
   – simple
• Cons
   – Only available in the kernel
   – Blocks everybody else, even with no contention
      • Slows interrupt response time
   – Does not work on a multiprocessor

                                                      20
Hardware Support for mutual
          exclusion
• Test and set instruction
  – Can be used to implement lock variables correctly
     • It loads the value of the lock
     • If lock == 0,
         – set the lock to 1
         – return the result 0 – we acquire the lock
     • If lock == 1
         – return 1 – another thread/process has the lock
  – Hardware guarantees that the instruction executes
    atomically.
     • Atomically: As an indivisible unit.

                                                            21
Mutual Exclusion with Test-and-Set




Entering and leaving a critical region using the
               TSL instruction
                                               22
Test-and-Set
• Pros
  – Simple (easy to show it’s correct)
  – Available at user-level
     • To any number of processors
     • To implement any number of lock variables
• Cons
  – Busy waits (also termed a spin lock)
     • Consumes CPU
     • Livelock in the presence of priorities
         – If a low priority process has the lock and a high priority process
           attempts to get it, the high priority process will busy-wait
           forever.
     • Starvation is possible when a process leaves its critical
       section and more than one process is waiting.
                                                                         23
Tackling the Busy-Wait Problem
• Sleep / Wakeup
  – The idea
    • When process is waiting for an event, it calls sleep
      to block, instead of busy waiting.
    • The the event happens, the event generator
      (another process) calls wakeup to unblock the
      sleeping process.




                                                       24
The Producer-Consumer
             Problem
• Also called the bounded buffer problem
• A producer produces data items and stores the
  items in a buffer
• A consumer takes the items out of the buffer and
  consumes them.
                                   Producer


              X   X    X

  Consumer


                                               25
Issues
• We must keep an accurate count of items in buffer
   – Producer
      • can sleep when the buffer is full,
      • and wakeup when there is empty space in the buffer
          – The consumer can call wakeup when it consumes the first entry of the
            full buffer
   – Consumer
      • Can sleep when the buffer is empty
      • And wake up when there are items available
          – Producer can call wakeup when it adds the first item to the buffer

                                                                           Producer


                                     X        X       X

                Consumer                                                         26
Pseudo-code for producer and
          consumer
int count = 0;               con() {
#define N 4 /* buf size */      while(TRUE) {
prod() {                            if (count == 0)
   while(TRUE) {                           sleep();
       item = produce()             remove_item();
       if (count == N)              count--;
              sleep();              if (count == N-1)
       insert_item();                      wakeup(prod);
       count++;                 }
       if (count == 1)       }
              wakeup(con);
   }
}

                                                      27
Problems
int count = 0;               con() {
#define N 4 /* buf size */      while(TRUE) {
prod() {                            if (count == 0)
   while(TRUE) {                            sleep();
       item = produce()             remove_item();
       if (count == N)              count--;
              sleep();              if (count == N-1)
       insert_item();                       wakeup(prod);
       count++;                 }
       if (count == 1)       }              Concurrent
              wakeup(con);                 uncontrolled
   }                                      access to the
                                              buffer
}

                                                       28
Problems
int count = 0;               con() {
#define N 4 /* buf size */      while(TRUE) {
prod() {                            if (count == 0)
   while(TRUE) {                            sleep();
       item = produce()             remove_item();
       if (count == N)              count--;
              sleep();              if (count == N-1)
       insert_item();                       wakeup(prod);
       count++;                 }
       if (count == 1)       }              Concurrent
              wakeup(con);                 uncontrolled
   }                                      access to the
                                              counter
}

                                                       29
Proposed Solution
• Lets use a locking primitive based on test-
  and-set to protect the concurrent access




                                           30
Proposed solution?
int count = 0;                con() {
#define N 4 /* buf size */       while(TRUE) {
prod() {                             if (count == 0)
   while(TRUE) {
                                            sleep();
        item = produce()
                                     acquire_lock()
        if (count == N)
               sleep();              remove_item();
        acquire_lock()               count--;
        insert_item();               release_lock();
        count++;                     if (count == N-1)
        release_lock()                      wakeup(prod);
        if (count == 1)          }
               wakeup(con);
                              }
   }
}

                                                       31
Problematic execution sequence
                                 con() {
                                    while(TRUE) {
                                         if (count == 0)
prod() {
   while(TRUE) {
         item = produce()
         if (count == N)                     wakeup without a
                  sleep();                  matching sleep is
         acquire_lock()                            lost
         insert_item();
         count++;
         release_lock()
         if (count == 1)
                  wakeup(con);
                                                  sleep();
                                         acquire_lock()
                                         remove_item();
                                         count--;
                                         release_lock();
                                         if (count == N-1)
                                                  wakeup(prod);
                                     }
                                                                  32
                                 }
Problem
• The test for some condition and actually
  going to sleep needs to be atomic

• The following does not work
acquire_lock()
if (count == N)
               sleep();
release_lock()


The lock is held while asleep ⇒ count will
 never change
                                             33
Semaphores
• Dijkstra (1965) introduced two primitives
  that are more powerful than simple sleep
  and wakeup alone.
  – P(): proberen, from Dutch to test.
  – V(): verhogen, from Dutch to increment.
  – Also called wait & signal, down & up.




                                              34
How do they work
• If a resource is not available, the corresponding
  semaphore blocks any process waiting for the resource
• Blocked processes are put into a process queue
  maintained by the semaphore (avoids busy waiting!)
• When a process releases a resource, it signals this by
  means of the semaphore
• Signalling resumes a blocked process if there is any
• Wait and signal operations cannot be interrupted
• Complex coordination can be implemented by multiple
  semaphores

                                                      35
Semaphore Implementation
• Define a semaphore as a record
        typedef struct {
          int count;
          struct process *L;
        } semaphore;

• Assume two simple operations:
  – sleep suspends the process that invokes it.
  – wakeup(P) resumes the execution of a blocked
    process P.

                                                   36
• Semaphore operations now defined as
     wait(S):
              S.count--;
              if (S.count < 0) {
                       add this process to S.L;
                       sleep;
              }

     signal(S):
              S.count++;
              if (S.count <= 0) {
                        remove a process P from S.L;
                        wakeup(P);
              }
• Each primitive is atomic

                                                       37
Semaphore as a General
          Synchronization Tool
• Execute B in Pj only after A executed in Pi
• Use semaphore count initialized to 0
• Code:
         Pi              Pj
          M               M
          A          wait(flag)
     signal(flag)        B

                                           38
Semaphore Implementation of a
           Mutex
• Mutex is short for Mutual Exclusion
   – Can also be called a lock
semaphore mutex;
mutex.count = 1; /* initialise mutex */

wait(mutex); /* enter the critcal region */

Blahblah();

signal(mutex); /* exit the critical region */
Notice that the initial count determines how many
 waits can progress before blocking and requiring
 a signal ⇒ mutex.count initialised as 1
                                                39
Solving the producer-consumer
        problem with semaphores
#define N = 4

semaphore mutex = 1;

/* count empty slots */
semaphore empty = N;

/* count full slots */
semaphore full = 0;




                                      40
Solving the producer-consumer
        problem with semaphores
prod() {                  con() {
   while(TRUE) {             while(TRUE) {
       item = produce()          wait(full);
       wait(empty);              wait(mutex);
       wait(mutex)               remove_item();
       insert_item();            signal(mutex);
       signal(mutex);            signal(empty);
       signal(full);         }
   }                      }
}




                                                  41
Summarising Semaphores
• Semaphores can be used to solve a
  variety of concurrency problems
• However, programming with then can be
  error-prone
  – E.g. must signal for every wait for mutexes
    • Too many, or too few signals or waits, or signals
      and waits in the wrong order, can have
      catastrophic results


                                                      42
Monitors
• To ease concurrent programming, Hoare (1974)
  proposed monitors.
  – A higher level synchronisation primitive
  – Programming language construct
• Idea
  – A set of procedures, variables, data types are
    grouped in a special kind of module, a monitor.
     • Variables and data types only accessed from within the
       monitor
  – Only one process/thread can be in the monitor at any
    one time
     • Mutual exclusion is implemented by the compiler (which
       should be less error prone)
                                                                43
Monitor
• When a thread
  calls a monitor
  procedure that
  has a thread
  already inside, it
  is queued and it
  sleeps until the
  current thread
  exits the monitor.




                                 44
Monitors




 Example of a monitor   45
Simple example
monitor counter {          Note: “paper” language
  int count;
                           • Compiler guarantees
  procedure inc() {
      count = count + 1;
                             only one thread can
  }
                             be active in the
  procedure dec() {
                             monitor at any one
      count = count –1;      time
  }                        • Easy to see this
}                            provides mutual
                             exclusion
                             – No race condition on
                               count.
                                                  46
How do we block waiting for an
          event?
• We need a mechanism to block waiting for
  an event (in addition to ensuring mutual
  exclusion)
  – e.g., for producer consumer problem when
    buffer is empty or full
• Condition Variables



                                               47
Condition Variable
• To allow a process to wait within the monitor, a condition
  variable must be declared, as
      condition x, y;
• Condition variable can only be used with the operations
  wait and signal.
   – The operation
      x.wait();
     means that the process invoking this operation is suspended until
     another process invokes
      x.signal();
   – The x.signal operation resumes exactly one suspended process. If
     no process is suspended, then the signal operation has no effect.

                                                              48
Condition Variables




                      49
Monitors




• Outline of producer-consumer problem with monitors
  – only one monitor procedure active at one time   50
  – buffer has N slots
OS/161 Provided Synchronisation
           Primitives
• Locks
• Semaphores
• Condition Variables




                               51
Locks
•   Functions to create and destroy locks

struct lock *lock_create(const char *name);
void         lock_destroy(struct lock *);

•   Functions to acquire and release them

void            lock_acquire(struct lock *);
void            lock_release(struct lock *);




                                               52
Example use of locks
int count;                   procedure inc() {
struct lock *count_lock         lock_acquire(count_lock);
                                count = count + 1;
main() {                        lock_release(count_lock);
   count = 0;                }
   count_lock =              procedure dec() {
       lock_create(“count       lock_acquire(count_lock);
   lock”);                      count = count –1;
   if (count_lock == NULL)      lock_release(count_lock);
       panic(“I’m dead”);    }
   stuff();
}



                                                      53
Semaphores
struct semaphore *sem_create(const char *name, int
                              initial_count);
void              sem_destroy(struct semaphore *);

void             P(struct semaphore *);
void             V(struct semaphore *);




                                                     54
Example use of Semaphores
int count;                    procedure inc() {
struct semaphore                 P(count_mutex);
   *count_mutex;                 count = count + 1;
                                 V(count_mutex);
main() {                      }
   count = 0;                 procedure dec() {
   count_mutex =                 P(count_mutex);
       sem_create(“count”,       count = count –1;
                     1);         V(count_mutex);
   if (count_mutex == NULL)   }
       panic(“I’m dead”);
   stuff();
}


                                                      55
Condition Variables
struct cv *cv_create(const char *name);
void       cv_destroy(struct cv *);

void        cv_wait(struct cv *cv, struct lock *lock);
    – Releases the lock and blocks
    – Upon resumption, it re-acquires the lock
        • Note: we must recheck the condition we slept on

void        cv_signal(struct cv *cv, struct lock *lock);
void        cv_broadcast(struct cv *cv, struct lock *lock);
    – Wakes one/all, does not release the lock
    – First “waiter” scheduled after signaller releases the lock will re-
      acquire the lock


Note: All three variants must hold the lock passed in.

                                                                       56
Condition Variables and Bounded
             Buffers
Non-solution            Solution
lock_acquire(c_lock)    lock_acquire(c_lock)
                        while (count == 0)
if (count == 0)
                          cv_wait(c_cv, c_lock);
             sleep();
                        remove_item();
remove_item();          count--;
count--;                lock_release(c_lock);
lock_release(c_lock);




                                              57
A Producer-Consumer Solution
         Using OS/161 CVs
int count = 0;
#define N 4 /* buf size */
prod() {                         con() {
   while(TRUE) {                    while(TRUE) {
        item = produce()                 lock_acquire(l)
        lock_aquire(l)                   while (count == 0)
        while (count == N)                      cv_wait(e,l);
               cv_wait(f,l);             item = remove_item();
        insert_item(item);               count--;
        count++;                         if (count == N-1)
        if (count == 1)                         cv_signal(f,l);
               cv_signal(e,l);           lock_release(l);
        lock_release()                   consume(item);
   }                                }
}                                }




                                                             58
Dining Philosophers


•   Philosophers eat/think
•   Eating needs 2 forks
•   Pick one fork at a time
•   How to prevent deadlock




                                  59
Dining Philosophers




                                               60
Solution to dining philosophers problem (part 1)
Dining Philosophers




A nonsolution to the dining philosophers problem
                                              61
Dining Philosophers




                                               62
Solution to dining philosophers problem (part 2)
The Readers and Writers Problem
• Models access to a database
    • E.g. airline reservation system
  – Can have more than one concurrent reader
    • To check schedules and reservations
  – Writers must have exclusive access
    • To book a ticket or update a schedule




                                               63
The Readers and Writers Problem




  A solution to the readers and writers problem 64

More Related Content

ODP
Sysprog 14
DOCX
Java 5 concurrency
PDF
Java Concurrency Gotchas
PDF
Observer pattern with Stl, boost and qt
PPT
Process Synchronization And Deadlocks
PPT
Transactions
ODP
Java memory model
PDF
Как мы охотимся на гонки (data races) или «найди багу до того, как она нашла ...
Sysprog 14
Java 5 concurrency
Java Concurrency Gotchas
Observer pattern with Stl, boost and qt
Process Synchronization And Deadlocks
Transactions
Java memory model
Как мы охотимся на гонки (data races) или «найди багу до того, как она нашла ...

What's hot (20)

PDF
Java Concurrency Gotchas
PPTX
Multi threading
PPT
Deuce STM - CMP'09
PDF
Java Concurrency Idioms
PDF
Java Course 5: Enums, Generics, Assertions
PPT
Clockless design language - ilia greenblat
PPTX
Threading in java - a pragmatic primer
PDF
Java Memory Model
PPTX
The Java memory model made easy
PPT
Dead locks9cm604.39
PPTX
Advanced Introduction to Java Multi-Threading - Full (chok)
PDF
Protocol T50: Five months later... So what?
PDF
[PH-Neutral 0x7db] Exploit Next Generation®
PPT
Operating System
PDF
Extending OpenJDK To Support Hybrid STM/HTM
PPTX
Deep Learning - Exploring The Magical World of Neural Network
PDF
XMOS XS1 and XC
PPTX
Thread syncronization
PDF
CS844 U1 Individual Project
PPTX
Николай Папирный Тема: "Java memory model для простых смертных"
Java Concurrency Gotchas
Multi threading
Deuce STM - CMP'09
Java Concurrency Idioms
Java Course 5: Enums, Generics, Assertions
Clockless design language - ilia greenblat
Threading in java - a pragmatic primer
Java Memory Model
The Java memory model made easy
Dead locks9cm604.39
Advanced Introduction to Java Multi-Threading - Full (chok)
Protocol T50: Five months later... So what?
[PH-Neutral 0x7db] Exploit Next Generation®
Operating System
Extending OpenJDK To Support Hybrid STM/HTM
Deep Learning - Exploring The Magical World of Neural Network
XMOS XS1 and XC
Thread syncronization
CS844 U1 Individual Project
Николай Папирный Тема: "Java memory model для простых смертных"
Ad

Viewers also liked (20)

PPTX
Slide comd
PPT
Arrangeren
PPT
Badalona-ILOQUID
DOCX
Marketing kisi2-2014
PPT
dMT SPC Presentation Products-engl.
PPTX
Commemoration of the Great War 1914-1918 by David Langford
PDF
49. upload lks 2015 web design (1)
PPT
Drawing human bodies
PPTX
TICs: redes educativas (ICTs: educational networks)
PDF
Lect17
PDF
非技術者のためのオープンソース入門 LibreOffice コミュニティで質問してみよう
PPTX
Innovation at OnTheWight - Presented at What's next for Community Journalism ...
PDF
Moianès-ILOQUID
PDF
Presentasi kpk
PDF
Gizmo spotの御案内(観光促進用)
PDF
Verbinden of verdwalen?
PPTX
http://commercialinsurance.inbuffalolocalarea.com/
ODS
сараа...тест
PPS
Paczka ciasteczek
Slide comd
Arrangeren
Badalona-ILOQUID
Marketing kisi2-2014
dMT SPC Presentation Products-engl.
Commemoration of the Great War 1914-1918 by David Langford
49. upload lks 2015 web design (1)
Drawing human bodies
TICs: redes educativas (ICTs: educational networks)
Lect17
非技術者のためのオープンソース入門 LibreOffice コミュニティで質問してみよう
Innovation at OnTheWight - Presented at What's next for Community Journalism ...
Moianès-ILOQUID
Presentasi kpk
Gizmo spotの御案内(観光促進用)
Verbinden of verdwalen?
http://commercialinsurance.inbuffalolocalarea.com/
сараа...тест
Paczka ciasteczek
Ad

Similar to Lect04 (20)

PPT
OS Process Synchronization, semaphore and Monitors
PPTX
Lecture 5 inter process communication
PPT
Ipc feb4
PDF
Synchronization
PDF
CH05.pdf
PPTX
synchronization in operating system structure
PPTX
UNIT-2 - Concurrency & Interprocess Communicatio.pptx
PPT
Chapter three- Process Synchronization.ppt
PDF
Lecture 5 process synchronization
PPT
Os module 2 c
PPT
Os module 2 c
PPTX
Synchronization hardware
PDF
Ch5 process synchronization
PDF
Lecture 5- Process Synchonization_revised.pdf
PDF
criticalsectionproblem-160905215747.pdf
PPTX
Critical section problem in operating system.
PPTX
Computer architecture related concepts, process
PPT
PPTX
Interactions complicate debugging
OS Process Synchronization, semaphore and Monitors
Lecture 5 inter process communication
Ipc feb4
Synchronization
CH05.pdf
synchronization in operating system structure
UNIT-2 - Concurrency & Interprocess Communicatio.pptx
Chapter three- Process Synchronization.ppt
Lecture 5 process synchronization
Os module 2 c
Os module 2 c
Synchronization hardware
Ch5 process synchronization
Lecture 5- Process Synchonization_revised.pdf
criticalsectionproblem-160905215747.pdf
Critical section problem in operating system.
Computer architecture related concepts, process
Interactions complicate debugging

More from Vin Voro (20)

PDF
Tele3113 tut6
PDF
Tele3113 tut5
PDF
Tele3113 tut4
PDF
Tele3113 tut1
PDF
Tele3113 tut3
PDF
Tele3113 tut2
PDF
Tele3113 wk11tue
PDF
Tele3113 wk10wed
PDF
Tele3113 wk10tue
PDF
Tele3113 wk11wed
PDF
Tele3113 wk7wed
PDF
Tele3113 wk9tue
PDF
Tele3113 wk8wed
PDF
Tele3113 wk9wed
PDF
Tele3113 wk7wed
PDF
Tele3113 wk7wed
PDF
Tele3113 wk7tue
PDF
Tele3113 wk6wed
PDF
Tele3113 wk6tue
PDF
Tele3113 wk5tue
Tele3113 tut6
Tele3113 tut5
Tele3113 tut4
Tele3113 tut1
Tele3113 tut3
Tele3113 tut2
Tele3113 wk11tue
Tele3113 wk10wed
Tele3113 wk10tue
Tele3113 wk11wed
Tele3113 wk7wed
Tele3113 wk9tue
Tele3113 wk8wed
Tele3113 wk9wed
Tele3113 wk7wed
Tele3113 wk7wed
Tele3113 wk7tue
Tele3113 wk6wed
Tele3113 wk6tue
Tele3113 wk5tue

Recently uploaded (20)

PPTX
Pharmacology of Heart Failure /Pharmacotherapy of CHF
PPTX
The Healthy Child – Unit II | Child Health Nursing I | B.Sc Nursing 5th Semester
PDF
FourierSeries-QuestionsWithAnswers(Part-A).pdf
PDF
Insiders guide to clinical Medicine.pdf
PPTX
human mycosis Human fungal infections are called human mycosis..pptx
PPTX
Introduction_to_Human_Anatomy_and_Physiology_for_B.Pharm.pptx
PDF
Origin of periodic table-Mendeleev’s Periodic-Modern Periodic table
PPTX
Institutional Correction lecture only . . .
PDF
ANTIBIOTICS.pptx.pdf………………… xxxxxxxxxxxxx
PPTX
PPT- ENG7_QUARTER1_LESSON1_WEEK1. IMAGERY -DESCRIPTIONS pptx.pptx
PDF
Mark Klimek Lecture Notes_240423 revision books _173037.pdf
PPTX
master seminar digital applications in india
PDF
Classroom Observation Tools for Teachers
PDF
01-Introduction-to-Information-Management.pdf
PPTX
Microbial diseases, their pathogenesis and prophylaxis
PPTX
Introduction to Child Health Nursing – Unit I | Child Health Nursing I | B.Sc...
PDF
Saundersa Comprehensive Review for the NCLEX-RN Examination.pdf
PPTX
Week 4 Term 3 Study Techniques revisited.pptx
PDF
Chapter 2 Heredity, Prenatal Development, and Birth.pdf
PPTX
IMMUNITY IMMUNITY refers to protection against infection, and the immune syst...
Pharmacology of Heart Failure /Pharmacotherapy of CHF
The Healthy Child – Unit II | Child Health Nursing I | B.Sc Nursing 5th Semester
FourierSeries-QuestionsWithAnswers(Part-A).pdf
Insiders guide to clinical Medicine.pdf
human mycosis Human fungal infections are called human mycosis..pptx
Introduction_to_Human_Anatomy_and_Physiology_for_B.Pharm.pptx
Origin of periodic table-Mendeleev’s Periodic-Modern Periodic table
Institutional Correction lecture only . . .
ANTIBIOTICS.pptx.pdf………………… xxxxxxxxxxxxx
PPT- ENG7_QUARTER1_LESSON1_WEEK1. IMAGERY -DESCRIPTIONS pptx.pptx
Mark Klimek Lecture Notes_240423 revision books _173037.pdf
master seminar digital applications in india
Classroom Observation Tools for Teachers
01-Introduction-to-Information-Management.pdf
Microbial diseases, their pathogenesis and prophylaxis
Introduction to Child Health Nursing – Unit I | Child Health Nursing I | B.Sc...
Saundersa Comprehensive Review for the NCLEX-RN Examination.pdf
Week 4 Term 3 Study Techniques revisited.pptx
Chapter 2 Heredity, Prenatal Development, and Birth.pdf
IMMUNITY IMMUNITY refers to protection against infection, and the immune syst...

Lect04

  • 2. Learning Outcomes • Understand concurrency is an issue in operating systems and multithreaded applications • Know the concept of a critical region. • Understand how mutual exclusion of critical regions can be used to solve concurrency issues – Including how mutual exclusion can be implemented correctly and efficiently. • Be able to identify and solve a producer consumer bounded buffer problem. • Understand and apply standard synchronisation primitives to solve synchronisation problems. 2
  • 4. Making Single-Threaded Code Multithreaded Conflicts between threads over the use of a global variable 4
  • 5. Inter- Thread and Process Communication We have a race condition Two processes want to access shared memory at same time 5
  • 6. Critical Region • We can control access to the shared resource by controlling access to the code that accesses the resource. ⇒ A critical region is a region of code where shared resources are accessed. – Variables, memory, files, etc… • Uncoordinated entry to the critical region results in a race condition ⇒ Incorrect behaviour, deadlock, lost work,… 6
  • 7. Critical Regions Mutual exclusion using critical regions 7
  • 8. Example critical sections struct node { void insert(struct *item) int data; { struct node *next; item->next = head; }; head = item; struct node *head; } void init(void) struct node *remove(void) { { head = NULL; struct node *t; } t = head; if (t != NULL) { head = head->next; • Simple last-in-first-out queue } implemented as a linked list. return t; } 8
  • 9. Example Race void insert(struct *item) void insert(struct *item) { { item->next = head; item->next = head; head = item; head = item; } } 9
  • 10. Example critical sections struct node { void insert(struct *item) int data; { struct node *next; item->next = head; }; head = item; struct node *head; } void init(void) struct node *remove(void) { { head = NULL; struct node *t; } t = head; if (t != NULL) { head = head->next; • Critical sections } return t; } 10
  • 11. Critical Regions Also called critical sections Conditions required of any solution to the critical region problem Mutual Exclusion: No two processes simultaneously in critical region No assumptions made about speeds or numbers of CPUs Progress No process running outside its critical region may block another process Bounded No process waits forever to enter its critical region 11
  • 12. A solution? • A lock variable – If lock == 1, • somebody is in the critical section and we must wait – If lock == 0, • nobody is in the critical section and we are free to enter 12
  • 13. A solution? while(TRUE) { while(TRUE) { while(lock == 1); while(lock == 1); lock = 1; lock = 1; critical(); critical(); lock = 0 lock = 0 non_critical(); non_critical(); } } 13
  • 14. A problematic execution sequence while(TRUE) { while(TRUE) { while(lock == 1); while(lock == 1); lock = 1; lock = 1; critical(); critical(); lock = 0 non_critical(); } lock = 0 non_critical(); } 14
  • 15. Observation • Unfortunately, it is usually easier to show something does not work, than it is to prove that it does work. – Ideally, we’d like to prove, or at least informally demonstrate, that our solutions work. 15
  • 16. Mutual Exclusion by Taking Turns Proposed solution to critical region problem (a) Process 0. (b) Process 1. 16
  • 17. 17
  • 18. Mutual Exclusion by Taking Turns • Works due to strict alternation – Each process takes turns • Cons – Busy waiting – Process must wait its turn even while the other process is doing something else. • With many processes, must wait for everyone to have a turn – Does not guarantee progress if a process no longer needs a turn. • Poor solution when processes require the critical section at differing rates 18
  • 19. Peterson’s Solution • See the textbook 19
  • 20. Mutual Exclusion by Disabling Interrupts • Before entering a critical region, disable interrupts • After leaving the critical region, enable interrupts • Pros – simple • Cons – Only available in the kernel – Blocks everybody else, even with no contention • Slows interrupt response time – Does not work on a multiprocessor 20
  • 21. Hardware Support for mutual exclusion • Test and set instruction – Can be used to implement lock variables correctly • It loads the value of the lock • If lock == 0, – set the lock to 1 – return the result 0 – we acquire the lock • If lock == 1 – return 1 – another thread/process has the lock – Hardware guarantees that the instruction executes atomically. • Atomically: As an indivisible unit. 21
  • 22. Mutual Exclusion with Test-and-Set Entering and leaving a critical region using the TSL instruction 22
  • 23. Test-and-Set • Pros – Simple (easy to show it’s correct) – Available at user-level • To any number of processors • To implement any number of lock variables • Cons – Busy waits (also termed a spin lock) • Consumes CPU • Livelock in the presence of priorities – If a low priority process has the lock and a high priority process attempts to get it, the high priority process will busy-wait forever. • Starvation is possible when a process leaves its critical section and more than one process is waiting. 23
  • 24. Tackling the Busy-Wait Problem • Sleep / Wakeup – The idea • When process is waiting for an event, it calls sleep to block, instead of busy waiting. • The the event happens, the event generator (another process) calls wakeup to unblock the sleeping process. 24
  • 25. The Producer-Consumer Problem • Also called the bounded buffer problem • A producer produces data items and stores the items in a buffer • A consumer takes the items out of the buffer and consumes them. Producer X X X Consumer 25
  • 26. Issues • We must keep an accurate count of items in buffer – Producer • can sleep when the buffer is full, • and wakeup when there is empty space in the buffer – The consumer can call wakeup when it consumes the first entry of the full buffer – Consumer • Can sleep when the buffer is empty • And wake up when there are items available – Producer can call wakeup when it adds the first item to the buffer Producer X X X Consumer 26
  • 27. Pseudo-code for producer and consumer int count = 0; con() { #define N 4 /* buf size */ while(TRUE) { prod() { if (count == 0) while(TRUE) { sleep(); item = produce() remove_item(); if (count == N) count--; sleep(); if (count == N-1) insert_item(); wakeup(prod); count++; } if (count == 1) } wakeup(con); } } 27
  • 28. Problems int count = 0; con() { #define N 4 /* buf size */ while(TRUE) { prod() { if (count == 0) while(TRUE) { sleep(); item = produce() remove_item(); if (count == N) count--; sleep(); if (count == N-1) insert_item(); wakeup(prod); count++; } if (count == 1) } Concurrent wakeup(con); uncontrolled } access to the buffer } 28
  • 29. Problems int count = 0; con() { #define N 4 /* buf size */ while(TRUE) { prod() { if (count == 0) while(TRUE) { sleep(); item = produce() remove_item(); if (count == N) count--; sleep(); if (count == N-1) insert_item(); wakeup(prod); count++; } if (count == 1) } Concurrent wakeup(con); uncontrolled } access to the counter } 29
  • 30. Proposed Solution • Lets use a locking primitive based on test- and-set to protect the concurrent access 30
  • 31. Proposed solution? int count = 0; con() { #define N 4 /* buf size */ while(TRUE) { prod() { if (count == 0) while(TRUE) { sleep(); item = produce() acquire_lock() if (count == N) sleep(); remove_item(); acquire_lock() count--; insert_item(); release_lock(); count++; if (count == N-1) release_lock() wakeup(prod); if (count == 1) } wakeup(con); } } } 31
  • 32. Problematic execution sequence con() { while(TRUE) { if (count == 0) prod() { while(TRUE) { item = produce() if (count == N) wakeup without a sleep(); matching sleep is acquire_lock() lost insert_item(); count++; release_lock() if (count == 1) wakeup(con); sleep(); acquire_lock() remove_item(); count--; release_lock(); if (count == N-1) wakeup(prod); } 32 }
  • 33. Problem • The test for some condition and actually going to sleep needs to be atomic • The following does not work acquire_lock() if (count == N) sleep(); release_lock() The lock is held while asleep ⇒ count will never change 33
  • 34. Semaphores • Dijkstra (1965) introduced two primitives that are more powerful than simple sleep and wakeup alone. – P(): proberen, from Dutch to test. – V(): verhogen, from Dutch to increment. – Also called wait & signal, down & up. 34
  • 35. How do they work • If a resource is not available, the corresponding semaphore blocks any process waiting for the resource • Blocked processes are put into a process queue maintained by the semaphore (avoids busy waiting!) • When a process releases a resource, it signals this by means of the semaphore • Signalling resumes a blocked process if there is any • Wait and signal operations cannot be interrupted • Complex coordination can be implemented by multiple semaphores 35
  • 36. Semaphore Implementation • Define a semaphore as a record typedef struct { int count; struct process *L; } semaphore; • Assume two simple operations: – sleep suspends the process that invokes it. – wakeup(P) resumes the execution of a blocked process P. 36
  • 37. • Semaphore operations now defined as wait(S): S.count--; if (S.count < 0) { add this process to S.L; sleep; } signal(S): S.count++; if (S.count <= 0) { remove a process P from S.L; wakeup(P); } • Each primitive is atomic 37
  • 38. Semaphore as a General Synchronization Tool • Execute B in Pj only after A executed in Pi • Use semaphore count initialized to 0 • Code: Pi Pj M M A wait(flag) signal(flag) B 38
  • 39. Semaphore Implementation of a Mutex • Mutex is short for Mutual Exclusion – Can also be called a lock semaphore mutex; mutex.count = 1; /* initialise mutex */ wait(mutex); /* enter the critcal region */ Blahblah(); signal(mutex); /* exit the critical region */ Notice that the initial count determines how many waits can progress before blocking and requiring a signal ⇒ mutex.count initialised as 1 39
  • 40. Solving the producer-consumer problem with semaphores #define N = 4 semaphore mutex = 1; /* count empty slots */ semaphore empty = N; /* count full slots */ semaphore full = 0; 40
  • 41. Solving the producer-consumer problem with semaphores prod() { con() { while(TRUE) { while(TRUE) { item = produce() wait(full); wait(empty); wait(mutex); wait(mutex) remove_item(); insert_item(); signal(mutex); signal(mutex); signal(empty); signal(full); } } } } 41
  • 42. Summarising Semaphores • Semaphores can be used to solve a variety of concurrency problems • However, programming with then can be error-prone – E.g. must signal for every wait for mutexes • Too many, or too few signals or waits, or signals and waits in the wrong order, can have catastrophic results 42
  • 43. Monitors • To ease concurrent programming, Hoare (1974) proposed monitors. – A higher level synchronisation primitive – Programming language construct • Idea – A set of procedures, variables, data types are grouped in a special kind of module, a monitor. • Variables and data types only accessed from within the monitor – Only one process/thread can be in the monitor at any one time • Mutual exclusion is implemented by the compiler (which should be less error prone) 43
  • 44. Monitor • When a thread calls a monitor procedure that has a thread already inside, it is queued and it sleeps until the current thread exits the monitor. 44
  • 45. Monitors Example of a monitor 45
  • 46. Simple example monitor counter { Note: “paper” language int count; • Compiler guarantees procedure inc() { count = count + 1; only one thread can } be active in the procedure dec() { monitor at any one count = count –1; time } • Easy to see this } provides mutual exclusion – No race condition on count. 46
  • 47. How do we block waiting for an event? • We need a mechanism to block waiting for an event (in addition to ensuring mutual exclusion) – e.g., for producer consumer problem when buffer is empty or full • Condition Variables 47
  • 48. Condition Variable • To allow a process to wait within the monitor, a condition variable must be declared, as condition x, y; • Condition variable can only be used with the operations wait and signal. – The operation x.wait(); means that the process invoking this operation is suspended until another process invokes x.signal(); – The x.signal operation resumes exactly one suspended process. If no process is suspended, then the signal operation has no effect. 48
  • 50. Monitors • Outline of producer-consumer problem with monitors – only one monitor procedure active at one time 50 – buffer has N slots
  • 51. OS/161 Provided Synchronisation Primitives • Locks • Semaphores • Condition Variables 51
  • 52. Locks • Functions to create and destroy locks struct lock *lock_create(const char *name); void lock_destroy(struct lock *); • Functions to acquire and release them void lock_acquire(struct lock *); void lock_release(struct lock *); 52
  • 53. Example use of locks int count; procedure inc() { struct lock *count_lock lock_acquire(count_lock); count = count + 1; main() { lock_release(count_lock); count = 0; } count_lock = procedure dec() { lock_create(“count lock_acquire(count_lock); lock”); count = count –1; if (count_lock == NULL) lock_release(count_lock); panic(“I’m dead”); } stuff(); } 53
  • 54. Semaphores struct semaphore *sem_create(const char *name, int initial_count); void sem_destroy(struct semaphore *); void P(struct semaphore *); void V(struct semaphore *); 54
  • 55. Example use of Semaphores int count; procedure inc() { struct semaphore P(count_mutex); *count_mutex; count = count + 1; V(count_mutex); main() { } count = 0; procedure dec() { count_mutex = P(count_mutex); sem_create(“count”, count = count –1; 1); V(count_mutex); if (count_mutex == NULL) } panic(“I’m dead”); stuff(); } 55
  • 56. Condition Variables struct cv *cv_create(const char *name); void cv_destroy(struct cv *); void cv_wait(struct cv *cv, struct lock *lock); – Releases the lock and blocks – Upon resumption, it re-acquires the lock • Note: we must recheck the condition we slept on void cv_signal(struct cv *cv, struct lock *lock); void cv_broadcast(struct cv *cv, struct lock *lock); – Wakes one/all, does not release the lock – First “waiter” scheduled after signaller releases the lock will re- acquire the lock Note: All three variants must hold the lock passed in. 56
  • 57. Condition Variables and Bounded Buffers Non-solution Solution lock_acquire(c_lock) lock_acquire(c_lock) while (count == 0) if (count == 0) cv_wait(c_cv, c_lock); sleep(); remove_item(); remove_item(); count--; count--; lock_release(c_lock); lock_release(c_lock); 57
  • 58. A Producer-Consumer Solution Using OS/161 CVs int count = 0; #define N 4 /* buf size */ prod() { con() { while(TRUE) { while(TRUE) { item = produce() lock_acquire(l) lock_aquire(l) while (count == 0) while (count == N) cv_wait(e,l); cv_wait(f,l); item = remove_item(); insert_item(item); count--; count++; if (count == N-1) if (count == 1) cv_signal(f,l); cv_signal(e,l); lock_release(l); lock_release() consume(item); } } } } 58
  • 59. Dining Philosophers • Philosophers eat/think • Eating needs 2 forks • Pick one fork at a time • How to prevent deadlock 59
  • 60. Dining Philosophers 60 Solution to dining philosophers problem (part 1)
  • 61. Dining Philosophers A nonsolution to the dining philosophers problem 61
  • 62. Dining Philosophers 62 Solution to dining philosophers problem (part 2)
  • 63. The Readers and Writers Problem • Models access to a database • E.g. airline reservation system – Can have more than one concurrent reader • To check schedules and reservations – Writers must have exclusive access • To book a ticket or update a schedule 63
  • 64. The Readers and Writers Problem A solution to the readers and writers problem 64