PTHREADS_ MUTEXES

download PTHREADS_ MUTEXES

of 13

Transcript of PTHREADS_ MUTEXES

  • 8/17/2019 PTHREADS_ MUTEXES

    1/13

    www2.chrishardick.com

    PTHREADS: MUTEXES

    the basic pthread synchronization mechanism

    mutex stands for mutual exclusion.

    the job of a mutex is to guarantee mutual exclusive access to a

    given resource (or set of resources)

    the most common method to synchronize common resources

    (global data, file descriptors, etc.) among threads is to ensure

    that only one thread is allowed to interact with the shared

    resource @ a given time. I.e. access to the shared resource ismutually exclusive (mutex)

    the most basic (& most common) usage is to create one mutex

    for each shared resource and to surround all access to the

    shared resouce w/ mutex_lock() & mutex_unlock() calls

    1. MUTEX DATATYPE: PTHREAD_MUTEX_T

    #include

    pthread_mutex_t my_mutex;

    READS: MUTEXES about:reader?url=http://www2.chrishardick.com/Notes/Computin

    3 3/3/2016 1

  • 8/17/2019 PTHREADS_ MUTEXES

    2/13

    an opaque type -- (see Opaque Datatypes)

    never copy a mutex - the result is undefined (it's opaque)

    if you need access to a mutex, you can copy a pointer to a

    mutex (into a function, etc.)

    2. MUTEX CREATION & DESTRUCTION

    In order to use a mutex, it must first be initialized (and initialized

    only once)

    There are two ways a mutex can be initialized

    static initialization1.

    dynamic initialization2.

    A. STATIC INITIALIZATION

    /*

     * statically initialize a mutex using

    PTHREAD_MUTEX_INITIALIZER macro

     */

    pthread_mutex_t StaticMutex =

    PTHREAD_MUTEX_INITIALIZER;

    statically initializes a mutex with default attributes.

    if you need to specify attributes, you must use dynamic

    initialization

    READS: MUTEXES about:reader?url=http://www2.chrishardick.com/Notes/Computin

    3 3/3/2016 1

  • 8/17/2019 PTHREADS_ MUTEXES

    3/13

    if you dynamically allocate a mutex, you must use dynamic

    initialization

    mutexes which are initialized statically do NOT need to be

    destroyed

    B. DYNAMIC INITIALIZATION

    /*

     * dynamically initialize a mutex

     *

     * RETURN * ======

     * 0 = success

     * else - see discussion on pthreads and errors

     */

    int pthread_mutex_init (pthread_mutex_t*

    p_Mutex, // in

      pthread_mutexattr_t*

    p_MutexAttr); // in: pass NULL for

    default attributes

    mutexes which are dynamically initialized need to be destroyed

    using pthread_mutex_destroy()

    you can safely destroy a mutex which has no thread(s) blocked

    on it & is unlocked

    how do you know if no threads are blocked on the mutex & that

    it is unlocked? You have to have a solid grasp of the program

    READS: MUTEXES about:reader?url=http://www2.chrishardick.com/Notes/Computin

    3 3/3/2016 1

  • 8/17/2019 PTHREADS_ MUTEXES

    4/13

    logic!!!

    /*

     * destroy a dynamically initialized mutex

     *

     * RETURN

     * ======

     * 0 = success

     * else - see discussion on pthreads and errors

     */

    int pthread_mutex_destroy (pthread_mutex_t*

    p_Mutex) // in

    /*

     * an example

     */

    #include

    #include // for strerror_r()

    char szEMsg[80];

    pthread_mutex_t* p_DynamicMutex =

    (pthread_mutex_t*) malloc

    (sizeof(pthread_mutex_t));

    int iRC = pthread_mutex_init (p_DynamicMutex,

    NULL);

    if (iRC != 0)

    {

    READS: MUTEXES about:reader?url=http://www2.chrishardick.com/Notes/Computin

    3 3/3/2016 1

  • 8/17/2019 PTHREADS_ MUTEXES

    5/13

  • 8/17/2019 PTHREADS_ MUTEXES

    6/13

    obtain the lock & own the mutex

     * - if mutex is already locked, you will block

     *

     * RETURN

     * ======

     * 0 = success

     * else - see discussion on pthreads and errors

     */

    int pthread_mutex_lock (pthread_mutex_t*

    p_Mutex); // in

    be careful NOT to lock a mutex when the calling thread already

    has the mutex locked; the behavior is undefined. On some

    systems, pthread_mutex_lock() will return an error, on other 

    systems, you'll be in a self-deadlock and never return

    Use pthread_mutex_unlock( ) to unlock a mutex

    You can ONLY unlock a mutex which is currently locked

    (owned) by the current thread

    2 corollaries: (1) you cannot unlock a mutex which is not locked

    & (2) you cannot unlock a mutex which was locked by another 

    thread

    mutex owner: the thread which obtained the lock on the mutex

    /*

     * unlock a mutex

     * - mutex must be owned by current thread

     * - unlock mutex & release ownership

    READS: MUTEXES about:reader?url=http://www2.chrishardick.com/Notes/Computin

    3 3/3/2016 1

  • 8/17/2019 PTHREADS_ MUTEXES

    7/13

     *

     * RETURN

     * ======

     * 0 = success

     * else - see discussion on pthreads and errors

     */

    int pthread_mutex_unlock (pthread_mutex_t*

    p_Mutex); // in

    Non-blocking Mutex Locks: pthread_mutex_trylock( )

    /*

     * lock a mutex - non-blocking version

     * - if mutex is not already locked, you will

    obtain the lock & own the mutex

     * - if mutex is already locked,

    pthread_mutex_trylock() will return

    immediately wth return value EBUSY

     * * RETURN

     * ======

     * 0 = success

     * EBUSY = mutex is currently locked

     * else - see discussion on pthreads and errors

     */

    int pthread_mutex_trylock (pthread_mutex_t*

    p_Mutex); // in

     A simple example

    /*

     * All accesses and modifications to x should

    READS: MUTEXES about:reader?url=http://www2.chrishardick.com/Notes/Computin

    3 3/3/2016 1

  • 8/17/2019 PTHREADS_ MUTEXES

    8/13

    be bracketed by calls to

    * pthread_mutex_lock() and

    pthread_mutex_unlock() as follows:

     */

    pthread_mutex_lock(&Mutex);

    /*

     * operate on x

    */

    pthread_mutex_unlock(&Mutex);

    4. MUTEX SIZE

    How much code should be within a mutex (i.e. how much

    data--and other shared resources--should be protected by a

    single mutex)?

    When converting existing non thread-safe code (e.g. an existing

    C library or (even worse) an existing fortran library), it's easiest

    to lock before entering and unlock after returning. This is known

    a a BIG MUTEX and depending on your situation, it might be

    your best (or only) solution

     As a general rule, resources which are usually used together 

    should use the same mutex. Unrelated resources should use

    separate mutexes

    5. AVOIDING DEADLOCKS

    READS: MUTEXES about:reader?url=http://www2.chrishardick.com/Notes/Computin

    3 3/3/2016 1

  • 8/17/2019 PTHREADS_ MUTEXES

    9/13

     Anytime your code need to hold more than one mutex @ a time,

    you have to be careful to avoid deadlock

    The classic deadlock

      Thread 1

    Thread 2

      ========

    ========

      lock mutex_a

    lock mutex_b

      | |

      lock mutex_b

    lock mutex_a

      - blocked forever waiting for mutex_b -

    blocked forever waiting for mutex_a

    Common techniques to avoid deadlocks are:

    establish a locking hierarchy1.

    spin lock2.

    chaining3.

    A. ESTABLISH A LOCKING HIERARCHY

    If a thread needs to hold multiple locks simultaneously, establish

    a hierarchy

    For example, mutex_a and mutex_b protect data which

    sometimes needs to be accessed simultaneously, establish a

    READS: MUTEXES about:reader?url=http://www2.chrishardick.com/Notes/Computin

    3 3/3/2016 1

  • 8/17/2019 PTHREADS_ MUTEXES

    10/13

    rule such that in order to lock both mutex_a and mutex_b,

    mutex_a must first be locked, followed by mutex_b

    Make sure you really need to hold both locks simultaneously.

    I.e. is it possible to release the 1st lock prior to obtaining the 2nd

    lock?

    Use whatever order makes the most sense -- so long as you

    always use the same order 

    Make a function to lock the set of mutexes (to enforce the

    correct order) -- be sure to document

    Unlocking the mutexes in whatever order makes the most

    sense. Unlocking can never result in deadlock, but some orders

    will probably be more effecient than others

    For a locking hierarchy, it usually makes the most sense to

    unlock in the same order 

    Make another function to unlock the set of mutexes

      Thread 1

    Thread 2

      ========

    ========

      lock mutex_a |

      lock mutex_b

    lock mutex_a (blocked)

      | |

      perform processing |

    READS: MUTEXES about:reader?url=http://www2.chrishardick.com/Notes/Computin

    13 3/3/2016 1

  • 8/17/2019 PTHREADS_ MUTEXES

    11/13

      | |

      unlock mutex_a |

      unlock mutex_b

    wake up (obtained mutex_a)

      |

    lock mutex_b

      ... |

    perform processing

      |

    unlock mutex_a

    unlock mutex_b

      |

      ...

    B. SPIN LOCK

    Lock the first mutex normally (blocking), but for any additional

    mutexes - use non-blocking mutexes (pthread_mutex_trylock())

    If any lock fails, unlock in reverse order and try again

    Unlocking the mutexes in the reverse order reduces the

    spinning for other threads

      Thread 1

    Thread 2

      ========

    ========

    READS: MUTEXES about:reader?url=http://www2.chrishardick.com/Notes/Computin

    13 3/3/2016 1

  • 8/17/2019 PTHREADS_ MUTEXES

    12/13

      lock mutex_a |

      try-lock mutex_b

    lock mutex_a (blocked)

      | |

      perform processing |

      | |

      unlock mutex_b |

      unlock mutex_a |

      |

    wake up (obtained mutex_a)

      ...

    try-lock mutex_b

      |

    perform processing

      |

    unlock mutex_b

    unlock mutex_a

    C. CHAINING

    Useful for traversing linked lists and other tree data structures

     A type of locking hierarchy

    Lock #1, Lock #2, Unlock #1, Lock #3, Unlock #2

      Thread 1

    ========

    READS: MUTEXES about:reader?url=http://www2.chrishardick.com/Notes/Computin

    13 3/3/2016 1

  • 8/17/2019 PTHREADS_ MUTEXES

    13/13

      lock head node

    head node processing

    |

    traverse branch locking first node

    unlock head node

    first node processing

    Back to PTHREADS

    READS: MUTEXES about:reader?url=http://www2.chrishardick.com/Notes/Computin