Document Sample
threads Powered By Docstoc
Multiple strands of execution in a single program are called threads. A thread is 'a sequence of
control within a process'. Normal Unix programs run as a single process. Indeed all processes
have at least one thread of execution.

Difference between fork and thread creation

When a process executes a fork call, a new copy of the process is created with its own variables
and its own PID. When we create a new thread in a process the new thread of execution gets its
own stack (and hence local variables) but shares global variables, file descriptors, signal handlers
and its current working directory state with its creator.

Posix Threads

Although Linux processes can share a large portion of their kernel data structures – an efficiently
measure known as lightweight process – each process has its own process descriptor. Each
execution context that can be independently scheduled must have its own process descriptor.

Lightweight processes should not be confused with user mode threads, which are different
execution flows handled by a user level library. For instance, older Linux systems implemented
POSIX threads entirely in user space by means of the pthread library, therefore a multithreaded
program was executed as a single Linux process. Currently, the pthread library, which has been
merged into standard C library, takes advantage of lightweight processes.

User-level Vs Kernel-level
 User-level manages the thread processes itself. (cooperative multitasking).
 User-level threads switch faster than kernel threads (in Linux there is not much difference)
 A user-level thread can monopolize the timeslice not letting other threads perform tasks.
 Kernel-level threads are implemented in the kernel. Kernel schedules each thread within
   timeslice of each process. Switching has bit more overhead but generally performance is
   almost as good as with user-level threads.

Threads on Linux

Thread support is available on most Linux distributions as a library.

The overhead of creating a new thread is significantly less than that of creating a new process.
Switching between threads, requires the operating system to do much less work than switching
between processes. Thus threads are much less demanding on resources than processes. Writing
multithreaded programs requires very careful thought. The potential for introducing subtle
timing faults, or faults caused by unintentional sharing of variables, in a multithreaded program
is considerable. In addition the programmer has to take care of thread synchronization and
mutual exclusions. Debugging a multithreaded program is much harder than a single threaded
Linux threads library provides following functions to create, manage and synchronize threads:

Thread Creation

int pthread_create ( pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void

Creates a new thread of control that executes concurrently with the calling thread. The thread
applies function 'start_routine' passing it 'arg' as argument. The new thread terminates either
explicitly by calling 'pthread_exit' or implicitly by returning from 'start_routine' function.

Thread Attributes

Setting attributes for threads is achieved by filling a thread attribute object 'attr' of type
'pthread_attr_t' then passing it as second argument to 'pthread_create'.

        pthread_attr_init ( pthread_attr_t *attr);
        pthread_attr_destroy ( pthread_attr_t *attr);
        pthread_attr_setdetachstate ( pthread_attr_t *attr, int detachstate);
        pthread_attr_getdetachstate ( const pthread_attr_t *attr, int *detachstate);
        pthread_attr_setschedparam ( pthread_attr_t *attr, const struct sched_param *param);
        pthread_attr_getschedparam ( const pthread_attr_t *attr, struct sched_param *param);
        pthread_attr_setschedpolicy ( pthread_attr_t *attr, int policy);
        pthread_attr_getschedpolicy ( const pthread_attr_t *attr, int *policy);
        pthread_attr_setinheritsched ( pthread_attr_t *attr, int inherit);
        pthread_attr_getinheritsched ( const pthread_attr_t *attr, int *inherit);
        pthread_attr_setscope ( pthread_attr_t *attr, int scope);
        pthread_attr_getscope ( const pthread_attr_t *attr, int *scope);

pthread_attr_init initialises 'attr' structure with the default attributes i.e.
pthread_attr_setdetachstate sets the thread's detach state to either
pthread_attr_setschedparam sets the thread's scheduling policy and priority.
pthread_attr_setschedpolicy sets the thread's scheduling policy to SCHED_OTHER or
pthread_attr_setinheritsched sets the source of threads's scheduling parameters either to
pthread_attr_setscope defines the scheduling contention scope of thread as

PTHREAD_CREATE_JOINABLE Created thread will be in joinable state. Another thread can
synchronize on thread termination and recover its termination code using 'pthread_join()'. Some
of the resources are kept allocated after thread terminates and reclaimed only when another
thread performs pthread_join(0) on that thread.
PTHREAD_CREATE_DETACH                 In the detached state, the thread resources are immediately
freed when it terminates, but pthread_join can not be used to synchronize on thread termination.
SCHED_OTHER           Regular non real-time scheduling
SCHED_FIFO            Real-time First In First Out scheduling will be applied to the thread
SCHED_RR              Real-time Round-Robin scheduling algorithm will be used.
PTHREAD_EXPLICIT_SCHED                Scheduling policy and parameters for the newly created
thread are detremined by the values of 'schedpolicy' and 'schedparam' attributes.
PTHREAD_INHERIT_SCHED                 Scheduling policy and priority are inherited from parent
PTHREAD_SCOPE_SYSTEM                  Threads contend for CPU time with all the processes
running on the machine.
PTHREAD_SCOPE_PROCESS                 Scheduling contention occurs only between the threads of
running process. (NOT supported on Linux)

POSIX Semaphores for Thread Synchronization

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

       int sem_init(sem_t *sem, int pshared, unsigned int value);
       int sem_wait(sem_t * sem);
       int sem_trywait(sem_t * sem);
       int sem_post(sem_t * sem);
       int sem_getvalue(sem_t * sem, int * sval);
       int sem_destroy(sem_t * sem);

'sem_init' initializes the semaphore object pointed to by 'sem'. The count associated with the
semaphore is set initially to 'value'. The 'pshared' argument indicates whether the semaphore is
local to the current process ( 'pshared' is zero) or is to be shared between several processes
'pshared' is not zero). LinuxThreads currently does not support process-shared semaphores, thus
sem_init always returns with error ENOSYS if pshared is not zero.

'sem_wait' suspends the calling thread until the semaphore pointed to by sem has non-zero
count. It then atomically decreases the semaphore count.

'sem_trywait' is a non-blocking variant of 'sem_wait'. If the semaphore pointed to by sem has
non-zero count, the count is atomically decreased and 'sem_trywait' immediately returns 0. If
the semaphore count is zero, 'sem_trywait' immediately returns with error EAGAIN.

'sem_post' atomically increases the count of the semaphore pointed to by 'sem'. This function
never blocks and can safely be used in asynchronous signal handlers.

'sem_getvalue' stores in the location pointed to by 'sval' the current count of the semaphore 'sem'.

'sem_destroy' destroys a semaphore object, freeing the resources it might hold. No threads
should be waiting on the semaphore at the time 'sem_destroy' is called. In the LinuxThreads
implementation, no resources are associated with semaphore objects, thus 'sem_destroy' actually
does nothing except checking that no thread is waiting on the semaphore.

POSIX Mutexes for Mutual Exclusion

A mutex is a MUTual EXclusion device, and is useful for protecting shared data structures from
concurrent modifications, and implementing critical sections and monitors.

A mutex has two possible states: unlocked (not owned by any thread), and locked (owned by one
thread). A mutex can never be owned by two different threads simultaneously. A thread
attempting to lock a mutex that is already locked by another thread is suspended until the owning
thread unlocks the mutex first.

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);

int pthread_mutex_lock(pthread_mutex_t *mutex));

int pthread_mutex_trylock(pthread_mutex_t *mutex);

int pthread_mutex_unlock(pthread_mutex_t *mutex);

int pthread_mutex_destroy(pthread_mutex_t *mutex);

'pthread_mutex_init' initializes the mutex object pointed to by 'mutex' according to the mutex
attributes specified in 'mutexattr'. If 'mutexattr' is NULL, default attributes are used instead.

The Linux Threads implementation supports only one mutex attributes, the mutex kind, which is
either "fast", "recursive", or "error checking". The kind of a mutex determines whether it can be
locked again by a thread that already owns it. The default kind is "fast".

Variables of type 'pthread_mutex_t' can also be initialized statically, using the constants
'PTHREAD_MUTEX_INITIALIZER' (for fast mutexes),
'PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP' (for recursive mutexes), and
'PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP' (for error checking mutexes).

'pthread_mutex_lock' locks the given mutex. If the mutex is currently unlocked, it becomes
locked and owned by the calling thread, and 'pthread_mutex_lock' returns immediately. If the
mutex is already locked by another thread, 'pthread_mutex_lock' suspends the calling thread until
the mutex is unlocked.

If the mutex is already locked by the calling thread, the behavior of 'pthread_mutex_lock'
depends on the kind of the mutex. If the mutex is of the "fast" kind, the calling thread is
suspended until the mutex is unlocked, thus effectively causing the calling thread to deadlock. If
the mutex is of the "error checking" kind, 'pthread_mutex_lock' returns immediately with the
error code EDEADLK. If the mutex is of the "recursive" kind, 'pthread_mutex_lock' succeeds
and returns immediately, recording the number of times the calling thread has locked the mutex.
An equal number of 'pthread_mutex_unlock' operations must be performed before the mutex
returns to the unlocked state.

'pthread_mutex_trylock' behaves identically to 'pthread_mutex_lock', except that it does not
block the calling thread if the mutex is already locked by another thread (or by the calling
thread in the case of a "fast" mutex). Instead, 'pthread_mutex_trylock' returns immediately with
the error code EBUSY.

'pthread_mutex_unlock' unlocks the given mutex. The mutex is assumed to be locked and owned
by the calling thread on entrance to 'pthread_mutex_unlock'. If the mutex is of the "fast" kind,
'pthread_mutex_unlock' always returns it to the unlocked state. If it is of the "recursive" kind, it
decrements the locking count of the mutex (number of 'pthread_mutex_lock' operations
performed on it by the calling thread), and only when this count reaches zero is the mutex
actually unlocked.

On "error checking" mutexes, 'pthread_mutex_unlock' actually checks at run-time that the
mutex is locked on entrance, and that it was locked by the same thread that is now calling
'pthread_mutex_unlock'. If these conditions are not met, an error code is returned and the mutex
remains unchanged. "Fast" and "recursive" mutexes perform no such checks, thus allowing a
locked mutex to be unlocked by a thread other than its owner. This is non-portable behavior and
must not be relied upon.

'pthread_mutex_destroy' destroys a mutex object, freeing the resources it might hold. The mutex
must be unlocked on entrance. In the LinuxThreads implementation, no resources are associated
with mutex objects, thus 'pthread_mutex_destroy' actually does nothing except checking that the
mutex is unlocked.


Shared By:
Tags: threads
Description: Interview questions and carreir developmwnt concept study materials,some tutorials
sreekanth reddy sreekanth reddy Software Engineer
About i am peaceful and kind person