multi-threaded programming - tu-varna · trifon ruskov technical university of varna 5 benefits of...

51
1 Multi-threaded Programming Trifon Ruskov [email protected] Technical University of Varna - Bulgaria

Upload: nguyendan

Post on 11-Apr-2018

220 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

1

Multi-threaded Programming

Trifon Ruskov [email protected]

Technical University of Varna - Bulgaria

Page 2: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 2

Threads

A thread is defined as an independent stream of instructions that can bescheduled to run as such by the operating system. We can think of a thread as basically a lightweight process:

A thread has an execution state (running, ready, etc.).The thread contexts saved when not running.Threads are able to be scheduled by the operating system and runas independent entities within a process.A thread has an execution stack and some per-thread static storage for local variables.A process can have multiple threads.A thread has access to the memory address space and resources of its process.

Page 3: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 3

Benefits of Threads vs. Processes

Less time to create a new thread than a process, because the newlycreated thread uses the current process address space.

Less time to terminate a thread than a process. Less time to switch between two threads within the same process,

partly because the newly created thread uses the current process address space.

Less communication overheads - communicating between the threads of one process is simple because the threads share everything: address space, in particular.

Page 4: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 4

Multi-threading vs. single-threading Single threading

When the OS does not support the concept of threads.Multi-threading

When the OS supports multiple threads of execution within a single process.

single process, single thread

single process, multiple threads

multiple processes, single thread

multiple processes, multiple threads

Examples of OS:MSDOS - supports a single

user process and a single thread UNIX - supports multiple

user processes but only supports one thread per process

Solaris - supports multiple threads

Page 5: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 5

Benefits of Multi-threaded Programming

Improve application responsiveness. Any program in which many activities are not dependent upon each other can be redesigned so that each activity is defined as a thread.

Use multiprocessors more efficiently. Typically, applications that express concurrency requirements with threads need not take into account the number of available processors. Applications with a high degree of parallelism, such as numerical algorithms and matrix multiplications, can run much faster when implemented with threads on a multiprocessor.

Improve program structure. Multi-threaded programs can be more adaptive to variations in user demands than single threaded programs.

Use fewer system resources. Programs with two or more processes that access common data through shared memory are applying more than one thread of control. The cost of creating and maintaining a large amount of process state information makes each process much more expensive than a thread in both time and address space.

Page 6: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 6

Models of Single and Multi-threaded Applications

Process Control Block

User Address Space

User Stack

Kernel Stack

Single-Threaded Process Model

Process Control Block

User Address Space

User Stack

Kernel Stack

Multithreaded Process Model

Thread Control Block

Thread

User Stack

Kernel Stack

Thread Control Block

Thread

User Stack

Kernel Stack

Thread Control Block

Thread

Page 7: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 7

Thread Levels

There are two broad categories of thread implementation:

User-level threads (ULT). The kernel is not aware of the existence of threads. All thread management is done by the application by using a thread library. Thread switching does not require kernelmode privileges and scheduling is application specific.

Kernel-level threads (KLT). All thread management is done by thekernel. No thread library but an API (system calls) to the kernel thread facility exists. The kernel maintains context information for the process and the threads, switching between threads requires the kernel. Scheduling is performed on a thread basis.

Page 8: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 8

Advantages and Disadvantages of User Level Threads

Advantages:Thread switching does not involve the kernel - no mode switching.Scheduling can be application specific - choose the best algorithm.User level threads can run on any OS - only needs a thread library.

Disadvantages:Most system calls are blocking and the kernel blocks processes - so all threads within the process will be blocked.The kernel can only assign processes to processors two. Two threadswithin the same process cannot run simultaneously on two processors.

Page 9: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 9

Advantages and Disadvantages of Kernel Level Threads (cont.)

Advantages:The kernel can simultaneously schedule many threads of the same process on many processors.Blocking is done on a thread level.Kernel routines can be multi-threaded.

Disadvantages:Thread switching within the same process involves the kernel. This results in a significant slowdown.

Page 10: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 10

Combined User and Kernel Level Approaches

Thread creation done in the user space.Bulk of scheduling and synchronization of threads done in the user space.The programmer may adjust the number of kernel level threads.Process includes the user's address space, stack, and process control block.User-level threads (threads library) invisible to the OS are the interface for application parallelism.Kernel threads are the unit that can be dispatched on a processor.Each lightweight process supports one or more ULTs and maps to exactly one KLT.

Page 11: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 11

Example of a Combined Approach

Solaris thread implementation

L L L L L L L

P

User-level thread

Kernel-level thread

L

Processor

Leight-weight Process

Hardware

Kernel

User

PPP

P

Page 12: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 12

Thread libraries

The interface to multi-threading support is through a subroutine library

The library must contain code for:creating and destroying threadspassing messages and data between threadsscheduling thread executionsaving and restoring thread contexts

Examples of thread libraries:libpthread for POSIX threadslibthread for Solaris threads

Page 13: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 13

The POSIX Thread library (Pthreads)

What are Pthreads ?

A standardized programming interface for UNIX systems. The interface has been specified by the IEEE POSIX 1003.1c standard (1995). Pthreads are defined as a set of C language programming types

and procedure calls, specified with a pthread.h. There are several drafts of the POSIX threads standard.The primary motivation for using Pthreads is to realize potential

program performance gains.

Page 14: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 14

Designing Threaded Programs

A program must be able to be organized into discrete, independenttasks which can execute concurrently. For example, if routine1 and routine2can be interchanged, interleaved and/or overlapped in real time, they are candidates for threading.

routine1 routine2 final routine

routine1routine2 final routine

r1 r2 final routiner1 r2 r1 r2

routine1routine1

routine2routine2final routinefinal routine

time

Page 15: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 15

Designing Threaded Programs (cont.)

Tasks that may be suitable for threading include tasks that:Block for potentially long waitsUse many CPU cyclesMust respond to asynchronous eventsAre of lesser or greater importance than other tasksAre able to be performed in parallel with other tasks

An application must not use libraries or other objects that don’t explicitly guarantee thread-safety!

Page 16: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 16

Common Models for Threaded Programs

Manager/Workers.A single thread, the manager, assigns work to other threads, the

workers. Typically, the manager handles all input and parcels out work to the other tasks. Two forms of the manager/worker model are common: static worker pool and dynamic worker pool.

Pipeline.A task is broken into a series of suboperations, each of which is

handled in series, but concurrently, by a different thread. For example -an automobile assembly line.

Peer.Similar to the manager/worker model, but after the main thread

creates other threads, it participates in the work.

Page 17: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 17

The Pthreads API

Three major classes of Pthreads subroutines:Thread management. This class of functions work directly on

threads - creating, detaching, joining, etc. They include functions to set/query thread attributes (joinable, scheduling etc.).

Mutexes. This class deal with synchronization, called a "mutex", which is an abbreviation for "mutual exclusion". Mutex functionsprovide for creating, destroying, locking and unlocking mutexes.

Condition variables. This class of functions address communications between threads that share a mutex. They are based upon programmer specified conditions.

All identifiers in the threads library begin with pthread_

Page 18: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 18

Thread Management. Creating Threadsint pthread_create(pthread_t *tid, const pthread_attr_t *tattr,

void*(*start_routine)(void *), void *arg);

Parameters:tid - Returned new thread ID.tattr - Specify a thread attributes object, or NULL for the default values.

This defines the thread as “joinable” (non detached) - its ID and other resources can not be reused as soon as the thread terminates.start_routine - The C routine that the thread will execute once it is created.arg - A single argument may be passed to start_routine.

This routine creates a new thread and makes it executable. Typically, threads are first created from within main() inside a single process. Once created, threads are peers, and may create other threads.

Initially, main() comprises a single, default thread. All other threads must be explicitly created by the programmer.

Page 19: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 19

Thread Management. Terminating Thread Execution

Ways in which a thread may be terminated:The thread returns from its first (outermost) procedure.The thread makes a call to the pthread_exit() subroutine.The thread is canceled by another thread via the pthread_cancel() routine

(not covered here).The entire process is terminated due to a call to either the exec or exit

subroutines.

void pthread_exit(void *status);

The pthread_exit() function terminates the calling thread. All thread-specific data bindings are released. If the calling thread is not detached, then the thread's ID and the exit status specified by status are retained until the thread is waited for (blocked). Otherwise, status is ignored and the thread's ID can be reclaimed immediately.

Use pthread_exit() to exit from all threads, especially main().

Page 20: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 20

Example: Thread Creation and Termination

#include <pthread.h>#include <stdio.h>#define NUM_THREADS 5

void *PrintHello(void *threadid){printf("\n%d: Hello World!\n", threadid);pthread_exit(NULL);

}

int main (int argc, char* argv[]){pthread_t threads[NUM_THREADS];int rc, t;for(t=0; t < NUM_THREADS; t++){printf("Creating thread %d\n", t);// Create a thread and pass its number as argumentrc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);if (rc){printf("ERROR: pthread_create %d\n", rc);exit(1);

}}pthread_exit(NULL);

}

Page 21: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 21

Thread Management. Joining Threads

"Joining" is one way to accomplish synchronization between threads.

int pthread_join(thread_t tid, void **status);

Parameters:tid – ID of a thread, which the current thread is waiting to end.status – Returned value of thread tid, which it gave as argument to

pthread_exit().

The pthread_join() function blocks the calling thread until the specified thread tid terminates. The specified thread must be in the current process.

It is impossible to join a detached thread.Multiple threads cannot wait for the same thread to terminate. If

they try to, one thread returns successfully and the others fail.

Page 22: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 22

Example: Threads Joining

#include <pthread.h>#include <stdio.h>#define NUM_THREADS 3

// A working threadvoid *BusyWork(void *null){

int i;double result=0.0;

// Simulate working for (i=0; i < 1000000; i++){

result = result + (double)random();}printf("result = %e\n",result);pthread_exit(NULL);

}

Page 23: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 23

Example: Threads Joining (cont.)int main (int argc, char* argv[]){

pthread_t thread[NUM_THREADS];int rc, t, status;

for(t=0; t < NUM_THREADS; t++){printf("Creating thread %d\n", t);// Create a thread as JOINABLErc = pthread_create(&thread[t], NULL, BusyWork, NULL); if (rc){

printf("ERROR: pthread_create %d\n", rc);exit(1);

}}for(t=0;t < NUM_THREADS;t++){

// Wait for other treadsrc = pthread_join(thread[t], (void **)&status);if (rc){

printf("ERROR: pthread_join %d\n", rc);exit(1);

}printf("Main: Completed join with thread %d status= %d\n",t,

status);}

pthread_exit(NULL);}

Page 24: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 24

Threads Attributes

Attributes are a way to specify behavior that is different from the default. When a thread is created with pthread_create() or when a synchronization variable is initialized, an attribute object can be specified. An attribute object is opaque, and cannot be directly modified by assignments. A set of functions is provided to initialize, configure, and destroy each object type. Once an attribute is initialized and configured, it has process-wide scope.

Attributes are specified only at thread creation time; they cannotbe altered while the thread is being used.

Page 25: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 25

Threads Attributes (cont.)

Non-real-time preemptive scheduling policy

SCHED_OTHERschedpolicy

New thread inherits parent thread scheduling policy

PTHREAD_INHERIT_SCHEDinheritsched

New thread has system allocated stack size

1 megabytestacksize

New thread has system allocated stack address

NULLstackaddr

Exit status and thread are preserved after the thread terminates

PTHREAD_CREATE_JOINABLEdetachstate

New thread is not permanently attached to LWP

PTHREAD_SCOPE_PROCESSscope

ResultDefault valueAttribute

Page 26: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 26

Example: Using Thread Attributes

#include <pthread.h>#include <stdio.h>#define NUM_THREADS 3

// A working threadvoid *BusyWork(void *null){

int i;double result=0.0;// Simulating a workfor (i=0; i < 1000000; i++){result = result + (double)random();

}printf("result = %e\n",result);pthread_exit(NULL);

}

Page 27: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 27

Example: Using Thread Attributes (cont.)

int main (int argc, char* argv[]){pthread_t thread[NUM_THREADS];pthread_attr_t attr; // Attribute objectint rc, t, status;

// Initialize and set thread detached attribute as joinablepthread_attr_init(&attr);pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE);

for(t=0;t < NUM_THREADS;t++){printf("Creating thread %d\n", t);rc = pthread_create(&thread[t], &attr, BusyWork, NULL); if (rc){printf("ERROR: pthread_create()is %d\n", rc);exit(1);

}}

Page 28: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 28

Example: Using Thread Attributes (cont.)

// Free attribute and wait for other threadspthread_attr_destroy(&attr);for(t=0; t < NUM_THREADS; t++){rc = pthread_join(thread[t], (void **)&status);if (rc){printf("ERROR: pthread_join()is %d\n", rc);exit(1);

}printf("Main: Completed join with thread %d status=

%d\n",t, status);}pthread_exit(NULL);

}

Page 29: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 29

Threads Synchronization

Methods of synchronizing threads:Mutual Exclusion (Mutex) locksCondition variablesSemaphores.

Synchronizing facility - synchronization objects:Variables in memory that are accessed just like data.Threads in different processes can communicate with each other.through synchronization objects.The objects are placed in threads-controlled shared memory.They can have lifetimes beyond that of the creating process.

Page 30: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 30

Threads Synchronization. Mutual Exclusion Locks

Mutual exclusion locks (mutexes) are a common method of serializing thread execution.

Mutual exclusion locks synchronize threads, usually by ensuring that only one thread at a time executes a critical section of code.

A typical sequence in the use of a mutex is as follows:Create and initialize a mutex variable.Several threads attempt to lock the mutex.Only one succeeds and that thread owns the mutex.The owner thread performs some set of actions.The owner unlocks the mutex.Another thread acquires the mutex and repeats the process.Finally the mutex is destroyed.

Page 31: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 31

Mutual Exclusion Locks. Initializing/Destroying a MutexTwo ways of initializing a mutex:

Statically, when it is declared. For example:

pthread_mutex_t mymutex = PTHREAD_MUTEX_INITIALIZER;

Dynamically. This method permits setting mutex object attributes.

int pthread_mutex_init(pthread_mutex_t *mp, const pthread_mutexattr_t *mattr);

Parameters:mp – pointer to mutex variable.mattr – attribute object, used to establish properties for the

mutex. Specified as NULL to accept defaults.

The mutex is initially unlocked.

Destorying a mutex:int pthread_mutex_destroy(pthread_mutex_t *mp);

Page 32: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 32

Mutual Exclusion Locks. Locking/Unlocking a Mutex

int pthread_mutex_lock(pthread_mutex_t *mp);

The function locks the mutex pointed to by mp. When the mutex is already locked, the calling thread blocks and waits on a prioritized queue. Whenpthread_mutex_lock() returns, the mutex is locked and the calling thread is the owner. The function returns zero after completing successfully. Any other returned value indicates that an error occurred.

int pthread_mutex_unlock(pthread_mutex_t *mp);

This function unlocks the mutex pointed to by mp. The mutex must be locked and the calling thread must be the one that last locked the mutex (i.e. the owner). When any other threads are waiting for the mutex to become available, the thread at the head of the queue is unblocked. The function returns zero after completing successfully. Any other returned value indicates that an error occurred.

Page 33: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 33

Example: Mutual Exclusion Locks#include <stdio.h>#include <pthread.h>int count=0;pthread_mutex_t mu; // The mutex variablevoid *inc_count(void* arg) {

int i=0;for (i=0;i<1000000;i++) {

pthread_mutex_lock(&mu);count++;pthread_mutex_unlock(&mu);if (i%100000==0) printf("+\n");

}pthread_exit(NULL);

}void *dec_count(void* arg) {

int i=0;for (i=0;i<1000000;i++) {

pthread_mutex_lock(&mu);count--;pthread_mutex_unlock(&mu);if (i%100000==0) printf("-\n");

}pthread_exit(NULL);

}

inc_count

count

+1 -1

mutex

dec_count

Page 34: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 34

Example: Mutual Exclusion Locks (cont.)

int main(int argc, char* argv[]) {pthread_t t1, t2;

// Initialize the mutex pthread_mutex_init(&mu, NULL);

pthread_create(&t1, NULL, inc_count, NULL);pthread_create(&t2, NULL, dec_count, NULL);

pthread_join(t1, NULL);pthread_join(t2, NULL);

// Free the mutex resources pthread_mutex_destroy(&mu);

printf("Main: Done.\n");

pthread_exit(NULL);}

Page 35: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 35

Deadlock

A problem:There is a need occasionally to access two resources at once. For

instance, one of the resources is in use, and then we discover that the other resource is needed as well.

If two threads attempt to claim both resources but lock the associated mutexes in different orders, deadlock happens.

Page 36: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 36

Example: Deadlock

void *thread1(void* arg) {int i=0;

for (i=0;i<10000000;i++) {pthread_mutex_lock(&m1);pthread_mutex_lock(&m2);

resource1++;if (resource1%1000000==0)

printf("thread1: resource2 %d\n", resource2);

pthread_mutex_unlock(&m2);pthread_mutex_unlock(&m1);

}pthread_exit(NULL);

}

void *thread2(void* arg) {int i=0;

for (i=0;i<10000000;i++) {pthread_mutex_lock(&m2);pthread_mutex_lock(&m1);

resource2++;if (resource2%1000000==0)

printf("thread2: resource1 %d\n", resource1);

pthread_mutex_unlock(&m2);pthread_mutex_unlock(&m1);

}pthread_exit(NULL);

}

Page 37: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 37

Avoiding Deadlock: Using Locking Hierarchies

The best way to avoid such deadlock problems is to use lock hierarchies: whenever threads lock multiple mutexes, they do so in the same order.

When locks are always taken in a prescribed order, deadlock should not occur.

void *thread2(void* arg) {int i=0;

for (i=0;i<10000000;i++) {pthread_mutex_lock(&m1);pthread_mutex_lock(&m2);

resource2++;if (resource2%1000000==0)

printf("thread2: resource1 %d\n", resource1);

pthread_mutex_unlock(&m2);pthread_mutex_unlock(&m1);

}pthread_exit(NULL);

}

void *thread1(void* arg) {int i=0;

for (i=0;i<10000000;i++) {pthread_mutex_lock(&m1);pthread_mutex_lock(&m2);

resource1++;if (resource1%1000000==0)

printf("thread1: resource2 %d\n", resource2);

pthread_mutex_unlock(&m2);pthread_mutex_unlock(&m1);

}pthread_exit(NULL);

}

Page 38: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 38

Avoiding Deadlock: Using conditional locking

Limitation of using locking hierarchies:Sometimes must take the mutexes in an order other than prescribed.

Solution:To prevent deadlock in such a situation, use conditional locking. One

thread must release its mutexes when it discovers that deadlock would otherwise be inevitable.

int pthread_mutex_trylock(pthread_mutex_t *mp);

The function will attempt to lock a mutex mp. However, if the mutex is already locked, the routine will return immediately with a "busy" error code. This routine may be useful in preventing deadlock conditions, as in a priority-inversion situation.

Page 39: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 39

Example: Using conditional locking

void *thread1(void* arg) {int i=0;

for (i=0;i<10000000;i++) {pthread_mutex_lock(&m1);pthread_mutex_lock(&m2);

resource1++;if (resource1%1000000==0)

printf("thread1: resource2%d\n", resource2);

pthread_mutex_unlock(&m2);pthread_mutex_unlock(&m1);

}pthread_exit(NULL);

}

void *thread2(void* arg) {int i=0;

for (i=0;i<10000000;i++) {// When there is a possibility of// deadlock, unlock the mutex (m2)for (;;) {

pthread_mutex_lock(&m2);if (pthread_mutex_trylock(&m1)==0)break;

pthread_mutex_unlock(&m2);}resource2++;if (resource2%1000000==0) {

printf("thread2: resource1 %d\n", resource1);

}pthread_mutex_unlock(&m1);pthread_mutex_unlock(&m2);

}pthread_exit(NULL);

}

Page 40: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 40

Threads Synchronization. Condition Variables

Condition variables can be used to atomically block threads until a particular condition is true. Condition variables are always used in conjunction with mutex locks:

• With a condition variable, a thread can atomically block until acondition is satisfied.

• The condition is tested under the protection of a mutual exclusion lock (mutex).

• When the condition is false, a thread usually blocks on a condition variable and atomically releases the mutex waiting for the condition to change.

• When another thread changes the condition, it can signal the associated condition variable to cause one or more waiting threads to wake up, acquire the mutex again, and re-evaluate the condition.

Page 41: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 41

Condition Variables. Initializing/Destroying a Condition

Two ways of initializing a condition variable:

Statically, when it is declared. For example:

pthread_condition_t mycond = PTHREAD_COND_INITIALIZER;

Dynamically. This method permits setting condition object attributes.

int pthread_cond_init(pthread_cond_t *cv, const pthread_condattr_t *cattr);

Parameters:cv – pointer to condition variable.cattr - attribute object, used to establish properties for the condition.

Specified as NULL to accept defaults.

Destorying a condition:int pthread_cond_destroy(pthread_cond_t *cv);

Page 42: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 42

Waiting / Signalling on Condition Variables

int pthread_cond_wait(pthread_cond_t *cv,pthread_mutex_t *mutex);

The function blocks the calling thread until the specified condition cv is signalled. This routine should be called while mutex mutex is locked, and it will automatically release the mutex while it waits. Should also unlock mutexafter a signal has been received.

int pthread_cond_signal(pthread_cond_t *cv);

The function routine is used to signal (or wake up) another thread which is waiting on condition variable cv. It should be called after mutex is locked, and must unlock mutex in order for pthread_cond_wait() routine to complete.

int pthread_cond_broadcast(pthread_cond_t *cv);

The pthread_cond_broadcast() routine should be used instead of pthread_cond_signal() if more than one thread is in a blocking wait state.

Page 43: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 43

Example: Using Condition Variables

// Two threads update a shared resource ‘count’.// The third thread waits until count variable reaches a // COUNT_LIMIT value. This thread is waken up by other treads.

#include <pthread.h>#include <stdio.h>

#define NUM_THREADS 3#define TCOUNT 10#define COUNT_LIMIT 12

int count = 0;int thread_ids[3] = {0,1,2};pthread_mutex_t count_mutex;pthread_cond_t count_limit_cv; // The condition variable

// Working thread, updating ‘count’void *inc_count(void *idp){int j,i;double result=0.0;int *my_id = idp;

Page 44: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 44

Example: Using Condition Variables (cont.)

for (i=0; i < TCOUNT; i++) {pthread_mutex_lock(&count_mutex);count++;// Check the value of ‘count’ and signal waiting thread // when condition is reached. if (count == COUNT_LIMIT) {

pthread_cond_signal(&count_limit_cv);printf("inc_count(): thread %d, count = %d Limit reached.\n",

*my_id, count);}printf("inc_count(): thread %d, count = %d, unlocking mutex\n",

*my_id, count);pthread_mutex_unlock(&count_mutex);

// Do some work so threads can workfor (j=0; j < 1000000; j++)

result = result + (double)random();}

pthread_exit(NULL);} // inc_count

Page 45: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 45

Example: Using Condition Variables (cont.)

// The waiting threadvoid *watch_count(void *idp){

int *my_id = idp;

printf("Starting watch_count(): thread %d\n", *my_id);

// Lock mutex and wait for signal.// If COUNT_LIMIT is reached before this routine is run, // the loop will be skipped to prevent pthread_cond_wait // from never returning. pthread_mutex_lock(&count_mutex);while (count < COUNT_LIMIT) {

pthread_cond_wait(&count_limit_cv, &count_mutex);printf("watch_count(): thread %d Condition signal

received.\n", *my_id);}pthread_mutex_unlock(&count_mutex);pthread_exit(NULL);

}

Page 46: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 46

Example: Using Condition Variables (cont.)

int main (int argc, char *argv[]){int i, rc;pthread_t threads[3];

// Initialize mutex and condition variable objects pthread_mutex_init(&count_mutex, NULL);pthread_cond_init(&count_limit_cv, NULL);

// Create threads in a joinable statepthread_create(&threads[0],NULL,inc_count,(void*)&thread_ids[0]);pthread_create(&threads[1],NULL,inc_count,(void*)&thread_ids[1]);pthread_create(&threads[2],NULL,watch_count,(void*)&thread_ids[2]);

for (i = 0; i < NUM_THREADS; i++) //Wait for all threads to complete pthread_join(threads[i], NULL);

printf ("Main: Waited on %d threads. Done.\n", NUM_THREADS);

// Clean up and exit pthread_mutex_destroy(&count_mutex);pthread_cond_destroy(&count_limit_cv);pthread_exit(NULL);

}

Page 47: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 47

Threads Synchronization. Semaphores

Semaphores are counters for resources shared between threads. The basic operations on semaphores are: increment the count atomically, and wait until the counter is non null and decrement it atomically.

Initializing the semaphore:int sem_init(sem_t *sem, int pshared, unsigned int value);

Parameters:sem – pointer to a semaphore objectpshared – indicates whether the semaphore is local to the current

process (zero) or is to be shared between several processes (non-zero).returns:

0 – on success-1 – on error (errno is set)

This function initialized the semaphore object pointed by sem. The count associated with the semaphore is set initially to value.

Page 48: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 48

Semaphores Operations

int sem_wait(sem_t *sem);

The function suspends the calling thread until semaphore pointed to by semhas non-zero count. It then atomically decreases the semaphore count.int sem_trywait(sem_t *sem);

The function is non-blocking variant of sem_wait(). If semaphore pointed to by sem has non-zero count, the count is atomically decreased and sem_trywait()immediately returns 0. If semaphore count is zero, the function immediately returns with error.int sem_post(sem_t *sem);

The function atomically increases the count of the semaphore pointed to by sem. This function never blocks and can safely be used in asynchronous signal handlers.int sem_getvalue(sem_t *sem, int *sval);

The function stores in the location pointed to by sval the current count of the semaphore sem.

Page 49: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 49

Example: Using Semaphores

#include <sys/types.h>#include <unistd.h>#include <pthread.h>#include <semaphore.h>#include <signal.h>

#define NUMTHREADS 5

sem_t semaphore; // The semaphore object

// Thread routine to wait on a semaphore.void *sem_waiter (void *arg){

int *id = (long)arg;

printf("Thread %d waiting\n", *id);sem_wait(&semaphore);printf("Thread %d resuming\n", *id);pthread_exit(NULL);

}

Page 50: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 50

Example: Using Semaphores (cont.)

int main (int argc, char *argv[]){int thread_count;pthread_t sem_waiters[NUMTHREADS];int status;

// Initialize the semaphoresif (sem_init(&semaphore, 0, 0) == -1) {

perror ("Init semaphore");exit(1);

}

// Create 5 threads to wait concurrently on the semaphore.for (thread_count=0; thread_count<NUMTHREADS; thread_count++) {

status = pthread_create(&sem_waiters[thread_count], NULL, sem_waiter, (void*)thread_count);

if (status != 0) {perror("Create thread");exit(1);

}}

Page 51: Multi-threaded Programming - TU-Varna · Trifon Ruskov Technical University of Varna 5 Benefits of Multi-threaded Programming Improve application responsiveness.Any program in which

Trifon Ruskov Technical University of Varna 51

Example: Using Semaphores (cont.)//"Broadcast" the semaphore by repeatedly posting until // the count of waiters goes to 0.while (1) {

int sem_value;if (sem_getvalue(&semaphore, &sem_value) == -1) {perror("Get semaphore value"); exit(1);

}if (sem_value > 0) break;printf ("Posting from main: %d\n", sem_value);if (sem_post(&semaphore) == -1) {perror("Post semaphore"); exit(1);

}}//Wait for all threads to complete.for (thread_count=0; thread_count<NUMTHREADS; thread_count++) {

status = pthread_join(sem_waiters[thread_count], NULL);if (status != 0) {perror("Join thread"); exit(1);

}}return 0;

}