0% found this document useful (0 votes)
3 views18 pages

Multithreading in Modern Applications

Uploaded by

shadman sakib
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views18 pages

Multithreading in Modern Applications

Uploaded by

shadman sakib
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Chapter-4

Motivation
Most modern applications are multithreaded

Threads run within application

Multiple tasks with the application can be implemented by separate threads

Update display

Fetch data

Spell checking

Answer a network request

Process creation is heavy-weight while thread creation is light-weight

Can simplify code, increase efficiency

Kernels are generally multithreaded

Chapter-4 1
Benefits
Responsiveness – may allow continued execution if part of process is blocked,
especially important for user interfaces

Resource Sharing – threads share resources of process, easier than shared


memory or message passing

Economy – cheaper than process creation, thread switching lower overhead than
context switching

Scalability –process can take advantage of multicore architectures

Multicore Programming
• Multicore or multiprocessor systems putting pressure on programmers, challenges
include:

Dividing activities

Balance

Data splitting

Data dependency

Chapter-4 2
Testing and debugging
• Parallelism implies a system can perform more than one task simultaneously

Concurrency supports more than one task making progress

Single processor / core, scheduler providing concurrency

Multicore Programming
• Types of parallelism

Data parallelism – distributes subsets of the same data across multiple cores,
same operation on each

Task parallelism – distributing threads across cores, each thread performing


unique operation

Chapter-4 3
User Threads and Kernel Threads
• User threads - management done by user-level threads library

• Three primary thread libraries:

Chapter-4 4
POSIX Pthreads

Windows threads

Java threads

• Kernel threads - Supported by the Kernel


• Examples – virtually all general -purpose operating systems, including:

Windows

Linux

Mac OS X

iOS

Android

Multithreading Models
Many-to-One

One-to-One

Many-to-Many

Many-to-One

Chapter-4 5
Many user-level threads mapped to single kernel thread

One thread blocking causes all to block

Multiple threads may not run in parallel on multicore system because only one may
be in kernel at a time

Few systems currently use this model

• Examples:

Solaris Green Threads

GNU Portable Threads

One-to-One

Chapter-4 6
Chapter-4 7
Thread Libraries
• Thread library provides programmer with API for creating and managing threads

• Two primary ways of implementing

Library entirely in user space

Kernel-level library supported by the OS

Pthreads
May be provided either as user-level or kernel-level

A POSIX standard (IEEE 1003.1c) API for thread creation and synchronization

Specification, not implementation

API specifies behavior of the thread library, implementation is up to development of


the library

Common in UNIX operating systems (Linux & Mac OS X)

Implicit Threading
Growing in popularity as numbers of threads increase, program correctness more
difficult with explicit threads

Creation and management of threads done by compilers and run-time libraries


rather than programmers

Chapter-4 8
Five methods explored

Thread Pools

Fork-Join

OpenMP

Grand Central Dispatch

Intel Threading Building Blocks

Fork-Join Parallelism

Chapter-4 9
Chapter-4 10
Chapter-4 11
Grand Central Dispatch
• Two types of dispatch queues:

• serial – blocks removed in FIFO order, queue is per process, called main
queue

Programmers can create additional serial queues within program

• concurrent – removed in FIFO order but several may be removed at a time

Chapter-4 12
Four system wide queues divided by quality of service:

QOS_CLASS_USER_INTERACTIVE
QOS_CLASS_USER_INITIATED
QOS_CLASS_USER_UTILITY
QOS_CLASS_USER_BACKGROUND

Threading Issues
Semantics of fork() and exec() system calls

Signal handling

Synchronous and asynchronous

Thread cancellation of target thread


Asynchronous or deferred

Thread-local storage

Scheduler Activations

Semantics of fork() and exec()


• Does fork()duplicate only the calling thread or all threads?

• Some UNIXes have two versions of fork

Chapter-4 13
• exec() usually works as normal – replace the running process including all threads

Signal Handling
Signals are used in UNIX systems to notify a process that a particular event has
occurred.

A signal handler is used to process signals

[Link] is generated by particular event


[Link] is delivered to a process
[Link] is handled by one of two signal handlers:
[Link]
[Link]-defined

• Every signal has default handler that kernel runs when handling signal

User-defined signal handler can override default

For single-threaded, signal delivered to process

Signal Handling (Cont.)


• Where should a signal be delivered for multi-threaded?

Deliver the signal to the thread to which the signal applies

Deliver the signal to every thread in the process

Deliver the signal to certain threads in the process

Assign a specific thread to receive all signals for the process

Chapter-4 14
Thread-Local Storage

Chapter-4 15
Thread-local storage (TLS) allows each thread to have its own copy of data

Useful when you do not have control over the thread creation process (i.e., when
using a thread pool)

Different from local variables

Local variables visible only during single function invocation

TLS visible across function invocations

Similar to static data

TLS is unique to each thread

Operating System Examples


Windows Threads

Linux Threads

Windows Threads

Chapter-4 16
Windows API – primary API for Windows applications

Implements the one-to-one mapping, kernel-level

Each thread contains

A thread id

Register set representing state of processor

Separate user and kernel stacks for when thread runs in user mode or
kernel mode

Private data storage area used by run-time libraries and dynamic link
libraries (DLLs)

• The register set, stacks, and private storage area are known as the context of the
thread

Windows Threads (Cont.)


• The primary data structures of a thread include:

ETHREAD (executive thread block) – includes pointer to process to which


thread belongs and to KTHREAD, in kernel space

KTHREAD (kernel thread block) – scheduling and synchronization info,


kernel-mode stack, pointer to TEB, in kernel space

TEB (thread environment block) – thread id, user-mode stack, thread-local


storage, in user space

Chapter-4 17
Chapter-4 18

Common questions

Powered by AI

Grand Central Dispatch (GCD) provides a robust mechanism for managing concurrent operations via serial and concurrent queues, automatically optimizing workloads across system resources . The use of GCD simplifies concurrency by abstracting thread creation and management away from the programmer. However, it introduces challenges in debugging and testing parallel code, as developers must be cautious of race conditions and deadlocks that arise from incorrect assumptions about execution order and data dependencies .

User-level threads are managed by a user-level threads library, which allows greater flexibility and portability but may suffer from performance issues, as blocking a thread may block the entire process . Kernel-level threads are managed by the operating system, offering better performance by allowing true parallelism and better utilization of multicore systems, since the OS can schedule them independently . However, kernel threads impose more overhead due to the need for frequent interactions with the kernel to manage states.

Thread-local storage (TLS) allows each thread to maintain its own copy of data, making it particularly useful in scenarios where thread creation is out of the programmer's control, such as when using thread pools . Unlike local variables that are confined to a single function invocation, TLS data persists across function calls, similar to static data, yet is specific to each thread. This is beneficial for storing state information and reducing contention for global data, thus improving thread independence and efficiency .

In multithreaded environments, the semantics of fork() can vary; it may duplicate only the calling thread or all threads in the process, posing challenges in maintaining consistent thread states and resources post-fork . Some UNIX systems offer two versions of fork() to address these challenges . The exec() system call typically replaces the entire process, including all threads, which simplifies its behavior in multithreaded contexts. However, using fork() in a multithreaded environment requires careful consideration of thread states and resource management to prevent issues such as deadlocks and synchronization errors .

The Many-to-One model maps many user-level threads to a single kernel thread, causing all user threads to block if one blocks, which limits parallel execution on multicore systems . The One-to-One model maps each user thread to a separate kernel thread, allowing true concurrent execution and better utilization of multicore systems, albeit with increased overhead due to more frequent kernel interactions . The Many-to-Many model maps many user-level threads to many kernel threads, striking a balance between resource overhead and parallel execution capabilities, making it suitable for applications requiring high responsiveness and concurrency .

In single-threaded applications, a signal is delivered to the process as a whole, with a default or user-defined signal handler managing it . In multi-threaded applications, signals can be directed to a specific thread, all threads, or a subset, as determined by the threading model and application requirements. Effective signal management strategies in multithreading involve assigning signal handling to a dedicated thread or ensuring that targeted threads adequately address signal delivery, minimizing unexpected disruptions and ensuring application robustness .

Data parallelism involves distributing subsets of the same data across multiple cores, performing the same operation on each subset, which can be challenging due to issues such as data splitting and dependency . Task parallelism, on the other hand, distributes different threads across cores, with each thread performing a unique operation. This approach requires careful coordination to balance the workload and ensure progress without data contention . Both techniques demand a deep understanding of the application workload to divide tasks or data efficiently and avoid bottlenecks.

Multithreading offers several advantages including increased responsiveness, as it allows continued execution even if part of the process is blocked, which is particularly beneficial for user interfaces . Resource sharing is simplified as threads share the resources of their parent process, making it easier than using shared memory or message passing. It is more economical because thread creation and context switching have lower overhead compared to process creation . Additionally, multithreading enhances scalability, allowing processes to leverage multicore architectures effectively . These benefits lead to improved system performance by utilizing resources more efficiently and reducing the time for task execution.

Scalability challenges in multicore architectures arise from the need to divide and balance workloads effectively while handling data dependencies across cores . Programmers must address these challenges by employing strategies like parallel algorithm design, workload partitioning, and data synchronization techniques to optimize resource usage and ensure balanced execution across cores. Approaches such as utilizing efficient concurrency libraries, leveraging implicit threading, and employing lock-free programming paradigms can mitigate overheads and improve scalability. Additionally, adopting design patterns like MapReduce or pipeline architectures can help in managing complex parallel workflows effectively .

Implicit threading shifts the responsibility of thread creation and management from the programmer to compilers and runtime libraries. This is significant as it simplifies application development, especially as the number of threads increases, which can make maintaining program correctness difficult . By automating and optimizing thread management, implicit threading reduces the potential for errors related to explicit thread handling, such as race conditions and deadlocks, thereby enhancing program reliability and easing the developer’s burden .

You might also like