intro threads

Upload: prudhvinadh-kopparapu

Post on 14-Apr-2018

219 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/27/2019 Intro Threads

    1/29

    An Introduction to

    Programming with Threads

  • 7/27/2019 Intro Threads

    2/29

    Resources

    Birrell - "An Introduction to

    Programming with Threads"

    Silberschatz et al., 7th ed, Chapter 4

  • 7/27/2019 Intro Threads

    3/29

    Threads

    A thread is a single sequential flow ofcontrol

    A process can have many threads and asingle address space

    Threads share memory and, hence, need to

    cooperate to produce correct results Thread has thread specific data (registers,

    stack pointer, program counter)

  • 7/27/2019 Intro Threads

    4/29

    Threads continued..

  • 7/27/2019 Intro Threads

    5/29

    Why use threads

    Threads are useful because of real-worldparallelism:

    input/output devices (flesh or silicon) may beslow but are independent -> overlap IO andcomputation

    distributed systems have many computing entities

    multi-processors/multi-core are becoming morecommon

    better resource sharing & utilization thenprocesses

  • 7/27/2019 Intro Threads

    6/29

    Thread Mechanisms

    Birrell identifies four mechanisms used inthreading systems: thread creation

    mutual exclusion

    waiting for events

    interrupting a threads wait

    In most mechanisms in current use, only thefirst three are covered

    In the paper - primitives used abstract, notderived from actual threading system or

    programming language!

  • 7/27/2019 Intro Threads

    7/29

    Example Thread Primitives

    Thread creation Threadtype

    Fork(proc, args)returns thread

    Join(thread)returns value

    Mutual Exclusion Mutex type

    Lock(mutex), a block-structured languageconstruct in this lecture

  • 7/27/2019 Intro Threads

    8/29

    Example Thread Primitives

    Condition Variables Conditiontype

    Wait(mutex, condition)

    Signal(condition)

    Broadcast(condition)

    Fork, Wait, Signal, etc. are not to be confusedwith the UNIX fork, wait, signal, etc.calls

  • 7/27/2019 Intro Threads

    9/29

    Creation Example

    {

    Thread thread1;

    thread1 = Fork(safe_insert, 4);

    safe_insert(6);

    Join(thread1); // Optional

    }

  • 7/27/2019 Intro Threads

    10/29

    Mutex Example

    list my_list;

    Mutex m;

    void safe_insert(int i) {

    Lock(m) {

    my_list.insert(i);

    }}

  • 7/27/2019 Intro Threads

    11/29

    Condition Variables

    Mutexes are used to control access to shared data only one thread can execute inside a Lock clause

    other threads who try to Lock, are blocked untilthe mutex is unlocked

    Condition variables are used to wait for specificevents

    free memory is getting low, wake up the garbagecollector thread

    10,000 clock ticks have elapsed, update thatwindow

    new data arrived in the I/O port, process it

    Could we do the same with mutexes?

    (think about it and well get back to it)

  • 7/27/2019 Intro Threads

    12/29

    Condition Variable Example

    Mutex io_mutex;

    Condition non_empty;

    ...

    Consumer:

    Lock (io_mutex) {while (port.empty())

    Wait(io_mutex, non_empty);

    process_data(port.first_in());

    }

    Producer:

    Lock (io_mutex) {

    port.add_data();

    Signal(non_empty);

    }

  • 7/27/2019 Intro Threads

    13/29

    Condition Variables Semantics

    Each condition variable is associated with asingle mutex

    Wait atomically unlocks the mutex and blocks

    the thread Signal awakes a blocked thread

    the thread is awoken inside Wait

    tries to lock the mutex

    when it (finally) succeeds, it returns from the Wait Doesnt this sound complex? Why do we do

    it? the idea is that the condition of the condition

    variable depends on data protected by the mutex

  • 7/27/2019 Intro Threads

    14/29

    Condition Variable Example

    Mutex io_mutex;

    Condition non_empty;

    ...

    Consumer:

    Lock (io_mutex) {while (port.empty())

    Wait(io_mutex, non_empty);

    process_data(port.first_in());

    }

    Producer:

    Lock (io_mutex) {

    port.add_data();

    Signal(non_empty);

    }

  • 7/27/2019 Intro Threads

    15/29

    Couldnt We Do the Same with PlainCommunication?Mutex io_mutex;...

    Consumer:

    Lock (io_mutex) {

    while (port.empty())

    go_to_sleep(non_empty);process_data(port.first_in());

    }

    Producer:

    Lock (io_mutex) {

    port.add_data();

    wake_up(non_empty);

    }

    Whats wrong with this? What if we dont lockthe mutex (or unlock it before going to sleep)?

  • 7/27/2019 Intro Threads

    16/29

    Mutexes and Condition Variables

    Mutexes and condition variables servedifferent purposes Mutex: exclusive access

    Condition variable: long waits

    Question: Isnt it weird to have both mutexes

    and condition variables? Couldnt a singlemechanism suffice?

    Answer:

  • 7/27/2019 Intro Threads

    17/29

    Use of Mutexes and ConditionVariables

    Protect shared mutable data:

    void insert(int i) {

    Element *e = new Element(i);

    e->next = head;

    head = e;

    }

    What happens if this code is run in twodifferent threads with no mutual

    exclusion?

  • 7/27/2019 Intro Threads

    18/29

    Using Condition Variables

    Mutex io_mutex;

    Condition non_empty;

    ...

    Consumer:

    Lock (io_mutex) {while (port.empty())

    Wait(io_mutex, non_empty);

    process_data(port.first_in());

    }

    Producer:

    Lock (io_mutex) {

    port.add_data();

    Signal(non_empty);

    }

    Why use while instead of if? (think of manyconsumers, simplicity of coding producer)

  • 7/27/2019 Intro Threads

    19/29

    Readers/WritersLocking

    Mutex counter_mutex;

    Condition read_phase,

    write_phase;

    int readers = 0;

    Reader:

    Lock(counter_mutex) {

    while (readers == -1)

    Wait(counter_mutex,

    read_phase);

    readers++;

    }

    ... //read data

    Lock(counter_mutex) {

    readers--;

    if (readers == 0)

    Signal(write_phase);

    }

    Writer:

    Lock(counter_mutex) {

    while (readers != 0)

    Wait(counter_mutex,

    write_phase);

    readers = -1;

    }... //write data

    Lock(counter_mutex) {

    readers = 0;

    Broadcast(read_phase);

    Signal(write_phase);}

  • 7/27/2019 Intro Threads

    20/29

    Comments on Readers/WritersExample

    Invariant: readers >= -1

    Note the use of Broadcast

    The example could be simplified by using a single condition

    variable for phase changes less efficient, easier to get wrong

    Note that a writer signals all potential readers and one potentialwriter. Not all can proceed, however

    (spurious wake-ups)

    Unnecessary lock conflicts may arise (especially formultiprocessors):

    both readers and writers signal condition variables while stillholding the corresponding mutexes

    Broadcast wakes up many readers that will contend for a mutex

  • 7/27/2019 Intro Threads

    21/29

    Readers/Writers Example

    Reader: Writer:Lock(mutex) { Lock(mutex) {

    while (writer) while (readers !=0 || writer)

    Wait(mutex, read_phase) Wait(mutex, write_phase)

    readers++; writer = true;

    } }

    // read data // write data

    Lock(mutex) { Lock(mutex) {

    readers--; writer = false;

    if (readers == 0) Broadcast(read_phase);

    Signal(write_phase); Signal(write_phase);

    } }

  • 7/27/2019 Intro Threads

    22/29

    Avoiding Unnecessary Wake-ups

    Reader:

    Lock(counter_mutex) {waiting_readers++;

    while (readers == -1)

    Wait(counter_mutex,

    read_phase);

    waiting_readers--;

    readers++;}

    ... //read data

    Lock(counter_mutex) {

    readers--;

    if (readers == 0)

    Signal(write_phase);}

    Writer:

    Lock(counter_mutex) {while (readers != 0)

    Wait(counter_mutex,

    write_phase);

    readers = -1;

    }

    ... //write dataLock(counter_mutex) {

    readers = 0;

    if (waiting_readers > 0)

    Broadcast(read_phase);

    else

    Signal(write_phase);}

    Mutex counter_mutex;Condition read_phase, write_phase;

    int readers = 0, waiting_readers =0;

  • 7/27/2019 Intro Threads

    23/29

    Problems With This Solution

    Explicit scheduling: readers always havepriority

    may lead to starvation (if there are alwaysreaders)

    fix: make the scheduling protocol morecomplicated than it is now

    To Do: Think about avoiding the problem of waking

    up readers that will contend for a singlemutex if executed on multiple processors

  • 7/27/2019 Intro Threads

    24/29

    Discussion Example

    Two kinds of threads, red and green, areaccessing a critical section. The critical sectionmay be accessed by at most three threads ofany kind at a time. The red threads havepriority over the green threads. Discuss the CS_enter and CS_exit code.

    Why do we need the red_waiting variable?

    Which condition variable should be signalledwhen?

    Can we have only one condition variable?

  • 7/27/2019 Intro Threads

    25/29

    Mutex m; Condition red_cond, green_cond;

    int red_waiting = 0; int green = 0, red = 0;

    Red:

    Lock(m) {

    // ???

    while (green + red == 3)

    Wait(m, red_cond);red++;

    // ???

    }

    ... //access data

    Lock(m) {

    red--;

    // ???

    // ???

    // ???

    }

    Green:

    Lock(m) {

    while (green + red == 3

    || red_waiting != 0)

    Wait(m, green_cond);green++;

    }

    ... //access data

    Lock(mutex) {

    green--;

    // ???

    // ???

    // ???

    }

  • 7/27/2019 Intro Threads

    26/29

    Deadlocks (brief)

    Well talk more later for now beware of deadlocks

    Examples:

    A locks M1, B locks M2, A blocks on M2, B blocks on M1

    Similar examples with condition variables and mutexes Techniques for avoiding deadlocks:

    Fine grained locking

    Two-phase locking: acquire all the locks youll ever needup front, release all locks if you fail to acquire any one

    very good technique for some applications, butgenerally too restrictive

    Order locks and acquire them in order (e.g., all threads firstacquire M1, then M2)

  • 7/27/2019 Intro Threads

    27/29

    MT and fork() and Thread-Safelibraries

    fork semantics forkall (e.g., Solaris fork()) forkone (e.g., Solaris fork1(), POSIX fork())

    ensure no mutexes needed by child process areheld by other threads in parent process (e.g.,pthread_atfork)

    Issue: mutex maybe be locked by parent at fork time ->child process will get its own copy of mutex with stateLOCKED and noone to unlock it!

    not all libraries are thread-safe must check to ensure use may have thread-safe alternatives

  • 7/27/2019 Intro Threads

    28/29

    Scope of multithreading

    LWPs, kernel and user threads

    kernel-level threads supported by the kernel Solaris, Linux, Windows XP/2000

    all scheduling, synchronization, thread structures maintained inkernel

    could write apps using kernel threads, but would have to go tokernel for everything

    user-level threads supported by a user-level library

    Pthreads, Java threads, Win32 sched. & synch can often be done fully in user space; kernel

    doesnt need to know there are many user threads

    problem with blocking on a system call

  • 7/27/2019 Intro Threads

    29/29

    Light Weight Processes - LWP

    These are virtual CPUs, can be multiple perprocess

    The scheduler of a threads library schedulesuser-level threads to these virtual CPUs

    kernel threads implement LWPs => visible tothe kernel, and can be scheduled

    sometimes LWP & kernel threads usedinterchangeably, but there can be kernelthreads without LWPs