0% found this document useful (0 votes)
233 views

Threads in Operating System

The document discusses processes and threads. It covers topics like process scheduling, thread behavior, benefits of using threads, and multithreading models. Threads allow for parallel execution with minimal overhead compared to processes.

Uploaded by

Monika Sahu
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
233 views

Threads in Operating System

The document discusses processes and threads. It covers topics like process scheduling, thread behavior, benefits of using threads, and multithreading models. Threads allow for parallel execution with minimal overhead compared to processes.

Uploaded by

Monika Sahu
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 103

Processes and Threads

Processes and their scheduling Multiprocessor scheduling Threads Distributed Scheduling/migration

Processes: Review
Multiprogramming versus multiprocessing Kernel data structure: process control block (PCB) Each process has an address space
Contains code, global and local variables..

Process state transitions Uniprocessor scheduling algorithms


Round-robin, shortest job first, FIFO, lottery scheduling, EDF

Performance metrics: throughput, CPU utilization, turnaround time, response time, fairness

Process Behavior
Processes: alternate between CPU and I/O CPU bursts
Most bursts are short, a few are very long (high variance) Modeled using hyperexponential behavior If X is an exponential r.v. Pr [ X <= x] = 1 e-mx E[X] = 1/m If X is a hyperexponential r.v. Pr [X <= x] = 1 p e-m1x -(1-p) e-m2x E[X] = p/ m1 + (1-p)/ m2

Process Scheduling
Priority queues: multiples queues, each with a different priority
Use strict priority scheduling Example: page swapper, kernel tasks, real-time tasks, user tasks

Multi-level feedback queue


Multiple queues with priority Processes dynamically move from one queue to another Depending on priority/CPU characteristics Gives higher priority to I/O bound or interactive tasks Lower priority to CPU bound tasks Round robin at each level

Introduction
A thread is a path of execution through a programs code, plus a set of resources (stack, register state, etc) assigned by the operating system.

Thread vs. Process


A Process is inert. A process never executes anything; it is simply a container for threads.
One thread of control through a large, potentially sparse address space Address space may be shared with other processes (shared mem) Collection of systems resources (files, semaphores)

Threads run in the context of a process. Each process has at least one thread. A thread represents a path of execution that has its own call stack and CPU state. Threads are confined to context of the process that created them.
A thread executes code and manipulates data within its processs address space. If two or more threads run in the context of a single process they share a common address space. They can execute the same code and manipulate the same data. Threads sharing a common process can share kernel object handles because the handles belong to the process, not individual threads.

Processes and Threads


Thread (light weight process)
A flow of control through an address space Each address space can have multiple concurrent control flows Each thread has access to entire address space Potentially parallel execution, minimal state (low overheads) May need synchronization to control access to shared variables

Threads
Each thread has its own stack, PC, registers
Share address space, files,

Single and Multithreaded Processes

Why use Threads?


Large multiprocessors need many computing entities (one per CPU) Switching between processes incurs high overhead With threads, an application can avoid per-process overheads
Thread creation, deletion, switching cheaper than processes

Threads have full access to address space (easy sharing) Threads can execute in parallel on multiprocessors

Starting a Process
Every time a process starts, the system creates a primary thread.
The thread begins execution with the C/C++ run-time librarys startup code. The startup code calls your main or WinMain and execution continues until the main function returns and the C/C++ library code calls ExitProcess.

Scheduling Threads
Windows 2000, NT and Win98 are preemptive multitasking systems. Each task is scheduled to run for some brief time period before another task is given control of CPU. Threads are the basic unit of scheduling on current Win32 platforms. A thread may be in one of three possible states:
running blocked or suspended, using virtually no CPU cycles ready to run, using virtually no CPU cycles

Scheduling Threads (continued)


A running task is stopped by the scheduler if:
it is blocked waiting for some system event or resource its time time slice expires and is placed back on the queue of ready to run threads it is suspended by putting itself to sleep for some time it is suspended by some other thread it is suspended by the operating system while the OS takes care of some other critical activity.

Blocked threads become ready to run when an event or resource they wait on becomes available. Suspended threads become ready to run when their sleep interval has expired or suspend count is zero.

Threads (Benefits)
Responsiveness
Program can continue even if part of it is blocked or is performing lengthy operation. Web browser can still allow user interaction in one thread during an image load thread

Resource sharing
Several different threads of activity within the same address space -share the code and data section

Economy
Costly Memory and resource allocation for process Comparatively time consuming to create and manage processes than threads Solaris: creating a process 30 times slower Context switching 5 times slower

Utilization of multiprocessor architecture

Benefits of using Threads


Keeping user interfaces responsive even if required processing takes a long time to complete.
handle background tasks with one or more threads service the user interface with a dedicated thread

Your program may need to respond to high priority events. In this case, the design is easier to implement if you assign that event handler to a high priority thread. Take advantage of multiple processors available for a computation. Avoid low CPU activity when a thread is blocked waiting for response from a slow device or human by allowing other threads to continue.

More Benefits
Improve robustness by isolating critical subsystems on their own threads of control. For simulations dealing with several interacting objects the program may be easier to design by assigning one thread to each object.

Potential Problems with Threads


Conflicting access to shared memory
one thread begins an operation on shared memory, is suspended, and leaves that memory region incompletely transformed a second thread is activated and accesses the shared memory in the corrupted state, causing errors in its operation and potentially errors in the operation of the suspended thread when it resumes

Race Conditions occur when:


correct operation depends on the order of completion of two or more independent activities the order of completion is not deterministic

Starvation
a high priority thread dominates CPU resources, preventing lower priority threads from running often enough or at all.

Problems with Threads (continued)


Priority inversion
a low priority task holds a resource needed by a higher priority task, blocking it from running

Deadlock
two or more tasks each own resources needed by the other preventing either one from running so neither ever completes and never releases its resource

Why Threads?
Single threaded process: blocking system calls, no parallelism Finite-state machine [event-based]: non-blocking with parallelism Multi-threaded process: blocking system calls with parallelism Threads retain the idea of sequential processes with blocking system calls, and yet achieve parallelism Software engineering perspective
Applications are easier to structure as a collection of threads Each thread performs several [mostly independent] tasks

Address Space for Multiple Threads


thread 1 stack 0xFFFFFFFF thread 2 stack SP thread 3 stack SP (T3) Virtual address space heap static data SP (T2) SP (T1)

0x00000000

PC

code (text)

PC (T2) PC (T1) PC (T3)

Multi-threaded Clients Example : Web Browsers


Browsers such as IE are multi-threaded Such browsers can display data before entire document is downloaded: performs multiple simultaneous tasks
Fetch main HTML page, activate separate threads for other parts Each thread sets up a separate connection with the server Uses blocking calls Each part (gif image) fetched separately and in parallel Advantage: connections can be setup to different sources Ad server, image server, web server

Multi-threaded Server Example


Apache web server: pool of pre-spawned worker threads
Dispatcher thread waits for requests For each request, choose an idle worker thread Worker thread uses blocking system calls to service web request

Solaris 2 Threads

Solaris Process

Thread Management
Creation and deletion of threads
Static versus dynamic

Critical sections
Synchronization primitives: blocking, spin-lock (busy-wait) Condition variables

Global thread variables Kernel versus user-level threads

Multithreading Models (Kernel Threads)


Many-to-Many Many-to-One

One-to-One

Many-to-Many Model
Allows many user level threads to be mapped to many kernel threads Allows the operating system to create a sufficient number of kernel threads Solaris prior to version 9 Windows NT/2000 with the Thread/Fiber package

Many-to-Many Model

Two-level Model
Similar to M:M, except it allows a specific thread to be bound to one kernel thread Examples
IRIX HP-UX Tru64 UNIX Solaris 8 and earlier

Two-level Model

Many-to-One
Many user-level threads mapped to single kernel thread Examples:
Solaris Green Threads GNU Portable Threads

Many-to-One
Many user-level threads mapped to single kernel thread. Used on systems that do not support kernel threads.

Many-to-One Model

One-to-One
Each user-level thread maps to kernel thread Examples
Windows NT/XP/2000 Linux Solaris 9 and later

One-to-one Model

Who creates and manages threads?


User-level implementation
done with function library (e.g., POSIX) Runtime system similar to process management except in user space Windows NT fibers: a user-level thread mechanism ???

Kernel implementation new system calls and new entity to manage


Linux: lightweight process (LWP) Windows NT & XP: threads

User Threads
Thread management done by user-level threads library Examples - POSIX Pthreads - Mach C-threads - Solaris threads

Kernel Threads
Supported by the Kernel Examples - Windows 95/98/NT/2000 - Solaris - Tru64 UNIX - BeOS - Linux

User-level versus kernel threads


Key issues: Cost of thread management
More efficient in user space

Ease of scheduling Flexibility: many parallel programming models and schedulers Process blocking a potential problem

User-level Threads
Threads managed by a threads library
Kernel is unaware of presence of threads

Advantages:
No kernel modifications needed to support threads Efficient: creation/deletion/switches dont need system calls Flexibility in scheduling: library can use different scheduling algorithms, can be application dependent

Disadvantages
Need to avoid blocking system calls [all threads block] Threads compete for one another Does not take advantage of multiprocessors [no real parallelism]

User-level threads

Kernel Threads
Supported by the Kernel
OS maintains data structures for thread state and does all of the work of thread implementation.

Examples
Solaris Tru64 UNIX Mac OS X Windows 2000/XP/Vista Linux version 2.6

Kernel Threads (continued)


OS schedules threads instead of processes Benefits
Overlap I/O and computing in a process Creation is cheaper than processes Context switch can be faster than processes

Negatives
System calls (high overhead) for operations Additional OS data space for each thread

Threads supported by processor


E.g., Pentium 4 with Hyperthreading
www.intel.com/products/ht/hyperthreading_more.htm

Multiple processor cores on a single chip


True concurrent execution within a single process

Requires kernel thread support Re-opens old issues


Deadlock detection Critical section management of synchronization primitives (especially in OS kernel)

Kernel-level threads
Kernel aware of the presence of threads
Better scheduling decisions, more expensive Better for multiprocessors, more overheads for uniprocessors

Light-weight Processes
Several LWPs per heavy-weight process User-level threads package
Create/destroy threads and synchronization primitives

Multithreaded applications create multiple threads, assign threads to LWPs (one-one, many-one, many-many) Each LWP, when scheduled, searches for a runnable thread [two-level scheduling]
Shared thread table: no kernel support needed

When a LWP thread block on system call, switch to kernel mode and OS context switches to another LWP

LWP Example

Thread Packages
Posix Threads (pthreads)
Widely used threads package Conforms to the Posix standard Sample calls: pthread_create, Typical used in C/C++ applications Can be implemented as user-level or kernel-level or via LWPs

Java Threads
Native thread support built into the language Threads are scheduled by the JVM

Unix Processes vs. Threads


On a 700 Mhz Pentium running Linux
Processes:
fork()/exit(): 250 microsec

Kernel threads:
pthread_create()/pthread_join(): 90 microsec

User-level threads:
pthread_create()/pthread_join(): 5 microsec

Pthreads
a POSIX standard (IEEE 1003.1c) API for thread creation and synchronization. API specifies behavior of the thread library, implementation is up to development of the library. Common in UNIX operating systems.

POSIX pthread Interface


Data type: pthread_t
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void*(*start_routine) (void), void *arg) ; creates a new thread of control new thread begins executing at start_routine pthread_exit(void *value_ptr) terminates the calling thread pthread_join(pthread_t thread, void **value_ptr); blocks the calling thread until the thread specified terminates pthread_t pthread_self() Returns the calling thread's identifier

Threads and small operating systems


Many small operating systems provide a common address space for all concurrent activities Each concurrent execution is like a Linux-Unix thread
But its often called a process! pthread interface and tools frequently used for

managing these processes

Windows 2000 Threads


Implements the one-to-one mapping. Each thread contains - a thread id - register set - separate user and kernel stacks - private data storage area

Linux Threads
Linux refers to them as tasks rather than threads. Thread creation is done through clone() system call. Clone() allows a child task to share the address space of the parent task (process)

Java Threads
Java threads may be created by:
Extending Thread class Implementing the Runnable interface

Java threads are managed by the JVM.

Java Thread States

Java Threads
Thread class Thread worker = new Thread(); Configure it Run it
public class application extends Thread { }

Methods to
Run, wait, exit Cancel, join Synchronize

Threading Issues
Semantics of fork() and exec() system calls for processes Thread cancellation Signal handling Kernel thread implementations
Thread pools Thread specific data Scheduler activations

Semantics of fork() and exec()


Does fork() duplicate only the calling thread or all threads?
Easy if user-level threads

Not so easy with kernel-level threads Linux has special clone() operation only forking thread is created in child process Windows XP has something similar

Thread Cancellation
Terminating a thread before it has finished Reason:
Some other thread may have completed the joint task E.g., searching a database

Issue:
Other threads may be depending cancelled thread for resources, synchronization, etc. May not be able to cancel one until all can be cancelled

Thread Cancellation (continued)


Two general approaches:
Asynchronous cancellation terminates the target thread immediately Deferred cancellation allows the target thread to periodically check if it should cancel itself
pthreads provides cancellation points

Signal Handling
Signals are used in Unix-Linux to notify process that a particular event has occurred e.g.
Divide-by-zero Illegal memory access, stack overflow, etc. CTL-C typed, or kill command issued at console Timer expiration; external alarm

A signal handler is used to process signals


Signal is generated by particular event Signal is delivered to a process Signal is handled by a signal handler

All processes provided with default signal handler Applications may install own handlers for specific signals

Signal Handling Options


Deliver signal to specific thread to which it applies
E.g., illegal memory access, divide-by-zero, etc.

Deliver signal to every thread in the process


CTL-C typed

Deliver signal to certain threads in the process


I.e., threads that have agreed to receive such signals (or not blocked them)

Assign a specific thread to receive all signals for the process


Kernel Thread Implementations


Linux Windows Others

Modern Linux Thread Implementation


Implemented directly in kernel Primary unit of scheduling and computation implemented by Linux 2.6 kernel A thread is just a special kind of process.
Robert Love, Linux Kernel Development, p.23

Every thread has its own task_struct in kernel

Definition
Task (from point of view of Linux kernel):
Process Thread Kernel thread (see later)

Modern Linux Threads (continued)


Process task_struct has pointer to own memory & resources Thread task_struct has pointer to processs memory & resources Kernel thread task_struct has null pointer to memory & resources
fork() and pthread_create() are library functions that invoke clone() system call Arguments specify what kind of clone

Modern Linux Threads (continued)


Threads are scheduled independently of each other Threads can block independently of each other
Even threads of same process

Threads can make their own kernel calls


Kernel maintains a small kernel stack per thread During kernel call, kernel is in process context

Process Context
0xFFFFFFFF
Kernel Space
stack
(dynamically allocated)

Kernel Code and Data

SP2 SP1

stack
(dynamically allocated)

Virtual
address space

User Space
heap
(dynamically allocated)

static data

0x00000000

code (text)

PC

32-bit Linux & Win XP 3G/1G user space/kernel space

Modern Linux Threads (continued)


Multiple threads can be executing in kernel at same time When in process context, kernel can
sleep on behalf of its thread take pages faults on behalf of its thread move data between kernel and process address space on behalf of thread

Linux Kernel Threads


Kernel has its own threads
No associated process context

Supports concurrent activity within kernel


Multiple devices operating at one time Multiple application activities at one time Multiple processors in kernel at one time

A useful tool
Special kernel thread packages, synchronization primitives, etc. Useful for complex OS environments

Windows XP Threads
Much like to Linux 2.6 threads
Primitive unit of scheduling defined by kernel Threads can block independently of each other Threads can make kernel calls

Process is a higher level (non-kernel) abstraction See Silbershatz, 22.3.2.2

Synchronization
A program may need multiple threads to share some data. If access is not controlled to be sequential, then shared data may become corrupted.
One thread accesses the data, begins to modify the data, and then is put to sleep because its time slice has expired. The problem arises when the data is in an incomplete state of modification. Another thread awakes and accesses the data, that is only partially modified. The result is very likely to be corrupt data.

The process of making access serial is called serialization or synchronization.

Thread Safety
Note that MFC is not inherently thread-safe. The developer must serialize access to all shared data. MFC message queues have been designed to be thread safe. Many threads deposit messages in the queue, the thread that created the (window with that) queue retrieves the messages. For this reason, a developer can safely use PostMessage and SendMessage from any thread. All dispatching of messages from the queue is done by the thread that created the window. Also note that Visual C++ implementation of the STL library is not thread-safe, and should not be used in a multi-threaded environment. I hope that will be fixed with the next release of Visual Studio, e.g., Visual Studio.Net.

MFC Support for Threads


CWinThread is MFCs encapsulation of threads and the Windows 2000 synchronization mechanisms, e.g.:
Events Critical Sections Mutexes Semaphores

MFC Threads
User Interface (UI) threads create windows and process messages sent to those windows Worker threads receive no direct input from the user.
Worker threads must not access a windows member functions using a pointer or reference. This will often cause a program crash. Worker threads communicate with a programs windows by calling the PostMessage and SendMessage functions. Often a program using worker threads will create user defined messages that the worker thread passes to a window to indirectly call some (event-handler) function. Inputs to the function are passed via the messages WPARAM and LPARAM arguments.

AfxBeginThread function that creates a thread: CWinThread *pThread = AfxBeginThread(ThreadFunc, &ThreadInfo); ThreadFunc the function executed by the new thread.

Creating Worker Threads in MFC

AFX_THREADPROC ThreadFunc(LPVOID pThreadInfo)

Creating UI Threads in MFC


Usually windows are created on the applications main thread. You can, however, create windows on a secondary UI thread. Heres how you do that:
Create a class, say CUIThread, derived from CWinThread. Use DECLARE_DYNCREATE(CUIThread) macro in the class declaration. Use IMPLEMENT_DYNCREATE(CUIThread, CWinThread) in implementation. Create windows Launch UI thread by calling: CWinThread *pThread = AfxBeginThread(RUNTIME_CLASS(CUIThread));

HANDLE hThrd = (HANDLE)_beginthread(ThreadFunc, 0, &ThreadInfo); ThreadFunc the function executed by the new thread void _cdecl ThreadFunc(void *pThreadInfo);

Creating Win32 Threads

pThreadInfo pointer to input parameters for the thread


Works just like the pThreadInfo on the previous slide.

For both threads created with AfxBeginThread and _beginthread the thread function, ThreadFunc, must be a global function or static member function of a class. It can not be a non-static member function.

Suspending and Running Threads SuspendThread. This Suspend a threads execution by calling
increments a suspend count. If the thread is running, it becomes suspended. pThread -> CWinThread::SuspendThread();

Calling ResumeThread decrements the suspend count. When the count goes to zero the thread is put on the ready to run list and will be resumed by the scheduler. pThread -> CWinThread::ResumeThread(); A thread can suspend itself by calling SuspendThread. It can also relinquish its running status by calling Sleep(nMS), where nMS is the number of milliseconds that the thread wants to sleep.

Thread Termination
ThreadFunc returns
Worker thread only Return value of 0 a normal return condition code

WM_QUIT
UI thread only

AfxEndThread( UINT nExitCode )


Must be called by the thread itself

::GetExitCode(hThread, &dwExitCode)
Returns the exit code of the last work item (thread, process) that has been terminated.

Wait For Objects


WaitForSingleObject makes one thread wait for:
Termination of another thread An event Release of a mutex Syntax: WaitForSingleObject(objHandle, dwMillisec)

WaitForMultipleObjects makes one thread wait for the elements of an array of kernel objects, e.g., threads, events, mutexes.
Syntax: WaitForMultipleObjects(nCount, lpHandles, fwait, dwMillisec) nCount: number of objects in array of handles lpHandles: array of handles to kernel objects fwait: TRUE => wait for all objects, FALSE => wait for first object dwMillisec: time to wait, can be INFINITE

Process Priority
IDLE_PRIORITY_CLASS
Run when system is idle

NORMAL_PRIORITY_CLASS
Normal operation

HIGH_PRIORITY_CLASS
Receives priority over the preceding two classes

REAL_TIME_PRIORITY_CLASS
Highest Priority Needed to simulate determinism

Thread Priority
You use thread priority to balance processing performance between the interfaces and computations.
If UI threads have insufficient priority the display freezes while computation proceeds. If UI threads have very high priority the computation may suffer. We will look at an example that shows this clearly.

Thread priorities take the values:


THREAD_PRIORITY_IDLE THREAD_PRIORITY_LOWEST THREAD_PRIORITY_BELOW_NORMAL THREAD_PRIORITY_NORMAL THREAD_PRIORITY_ABOVE_NORMAL THREAD_PRIORITY_HIGHEST THREAD_PRIORITY_TIME_CRITICAL

Thread Synchronization
Synchronizing threads means that every access to data shared between threads is protected so that when any thread starts an operation on the shared data no other thread is allowed access until the first thread is done. The principle means of synchronizing access to shared data are:
Interlocked increments only for incrementing or decrementing integers Critical Sections Good only inside one process Mutexes Named mutexes can be shared by threads in different processes. Events Useful for synchronization as well as other event notifications.

Interlocked Operations
InterlockedIncrement increments a 32 bit integer as an atomic operation. It is guaranteed to complete before the incrementing thread is suspended. long value = 5; InterlockedIncrement(&value); InterlockedDecrement decrements a 32 bit integer as an atomic operation: InterlockedDecrement(&value);

Win32 Critical Sections


Threads within a single process can use critical sections to ensure mutually exclusive access to critical regions of code. To use a critical section you:
allocate a critical section structure initialize the critical section structure by calling a win32 API function enter the critical section by invoking a win32 API function leave the critical section by invoking another win32 function. When one thread has entered a critical section, other threads requesting entry are suspended and queued waiting for release by the first thread.

The win32 API critical section functions are:


InitializeCriticalSection(&GlobalCriticalSection) EnterCriticalSection(&GlobalCriticalSection) TryEnterCriticalSection(&GlobalCriticalSection) LeaveCriticalSection(&GlobalCriticalSection) DeleteCriticalSection(&GlobalCriticalSection)

MFC Critical Sections


A critical section synchronizes access to a resource shared between threads, all in the same process.
CCriticalSection constructs a critical section object CCriticalSection::Lock() locks access to a shared resource for a single thread. CCriticalSection::Unlock() unlocks access so another thread may access the shared resource
CCriticalSection cs; cs.Lock(); // operations on a shared resource, e.g., data, an iostream, file cs.Unlock();

Win32 Mutexes
Mutually exclusive access to a resource can be guaranteed through the use of mutexes. To use a mutex object you:
identify the resource (section of code, shared data, a device) being shared by two or more threads declare a global mutex object program each thread to call the mutexs acquire operation before using the shared resource call the mutexs release operation after finishing with the shared resource

The mutex functions are:


CreateMutex WaitForSingleObject WaitForMultipleObjects ReleaseMutex

MFC Mutexes
A mutex synchronizes access to a resource shared between two or more threads. Named mutexes are used to synchronize access for threads that reside in more than one process.
CMutex constructs a mutex object Lock locks access for a single thread Unlock releases the resource for acquisition by another thread
CMutex cm; cm.Lock(); // access a shared resource cm.Unlock(); CMutex objects are automatically released if the holding thread terminates.

Win32 Events
Events are objects which threads can use to serialize access to resources by setting an event when they have access to a resource and resetting the event when through. All threads use WaitForSingleObject or WaitForMultipleObjects before attempting access to the shared resource. Unlike mutexes and semaphores, events have no predefined semantics.
An event object stays in the nonsignaled stated until your program sets its state to signaled, presumably because the program detected some corresponding important event. Auto-reset events will be automatically set back to the non-signaled state after a thread completes a wait on that event. After a thread completes a wait on a manual-reset event the event will return to the non-signaled state only when reset by your program.

Win32 Events (continued)


Event functions are:
CreateEvent OpenEvent SetEvent PulseEvent WaitForSingleEvent WaitForMultipleEvents

MFC Events
An event can be used to release a thread waiting on some shared resource (refer to the buffer writer/reader example in pages 10181021). A named event can be used across process boundaries. CEvent constructs an event object. SetEvent() sets the event. Lock() waits for the event to be set, then automatically resets it. CEvent ce; : ce.Lock(); // called by reader thread to wait for writer : ce.SetEvent(); // called by writer thread to release reader

CSingleLock & CMultiLock


CSingleLock and CMultiLock classes can be used to wrap critical sections, mutexes, events, and semaphores to give them somewhat different lock and unlock semantics. CCriticalSection cs; CSingleLock slock(cs); slock.Lock(); // do some work on a shared resource slock.Unlock(); This CSingleLock object will release its lock if an exception is thrown inside the synchronized area, because its destructor is called. That does not happen for the unadorned critical section.

Threads Summary
Threads were invented to counteract the heavyweight nature of Processes in Unix, Windows, etc. Provide lightweight concurrency within a single address space Have evolved to become primitive abstraction defined by kernel
Fundamental unit of scheduling in Linux, Windows, etc

Review
Threads introduced because
Processes are heavyweight in Windows and Linux Difficult to develop concurrent applications when address space is unique per process

Thread a particular execution of a program within the context of a Windows-Unix-Linux process


Multiple threads in same address space at same time

This problem
is partly an artifact of
Unix, Linux, and Windows
and of

Big, powerful processors (e.g., Pentium, Athlon)

tends to occur in most large systems is infrequent in small-scale systems


PDAs, cell phones Closed systems (i.e., controlled applications)

Characteristics
A thread has its own
Program counter, registers, PSW Stack

A thread shares
Address space, heap, static data, program code Files, privileges, all other resources

with all other threads of the same process

Sample Pthreads Program in C, C++


The program in C++ calls the pthread.h header file. Pthreads related statements are preceded by the pthread_ prefix (except for semaphores). Knowing how to manipulate pointers is important.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

//**************************************************************** // This is a sample threaded program in C++. The main thread creates // 4 daughter threads. Each daughter thread simply prints out a message // before exiting. Notice that Ive set the thread attributes to joinable and // of system scope. //**************************************************************** #include <iostream.h> #include <stdio.h> #include <pthread.h>
#define NUM_THREADS 4 void *thread_function( void *arg ); int main( void ) { int i, tmp; int arg[NUM_THREADS] = {0,1,2,3}; pthread_t thread[NUM_THREADS]; pthread_attr_t attr; // initialize and set the thread attributes pthread_attr_init( &attr ); pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_JOINABLE ); pthread_attr_setscope( &attr, PTHREAD_SCOPE_SYSTEM );

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

// creating threads for ( i=0; i<NUM_THREADS; i++ ) { tmp = pthread_create( &thread[i], &attr, thread_function, (void *)&arg[i] ); if ( tmp != 0 ) { cout << "Creating thread " << i << " failed!" << endl; return 1; } } // joining threads for ( i=0; i<NUM_THREADS; i++ ) { tmp = pthread_join( thread[i], NULL ); if ( tmp != 0 ) { cout << "Joing thread " << i << " failed!" << endl; return 1; } } return 0; }

54 55 56 57 58 59 60 61 62 63 64 65 66

//*********************************************************** // This is the function each thread is going to run. It simply asks // the thread to print out a message. Notice the pointer acrobatics. //*********************************************************** void *thread_function( void *arg ) { int id; id = *((int *)arg); printf( "Hello from thread %d!\n", id ); pthread_exit( NULL ); }

How to compile:
in Linux use:
> {C++ comp} D_REENTRANT hello.cc lpthread o hello

it might also be necessary for some systems to define the _POSIX_C_SOURCE (to 199506L)

Creating a thread:
int pthread_create( pthread_t *thread, pthread_attr_t *attr, *), void *arg ); void *(*thread_function)(void

first argument pointer to the identifier of the created thread second argument thread attributes third argument pointer to the function the thread will execute fourth argument the argument of the executed function (usually a struct) returns 0 for success

You might also like