Multitasking

Multitasking is the concept that encompasses multi-threading and multi-processing to achieve concurrent program executions.

Table of contents

Multiprogramming

Multiprogramming is a technique that allows multiple programs to reside in memory simultaneously, enabling the CPU to switch between the programs when the current program is waiting for I/O operations. This maximizes CPU utilization by reducing idle time. However, in multiprogramming, context switches occur primarily when a program voluntarily yields control (e.g., during I/O waits).

Multitasking is a logical extension of Multiprogramming

Multitasking, as a logical extension, introduces time-sharing through frequent context switches based on a fixed time quantum and some supportive data structure (i.e. multi-level priority queue). This mechanism is called as time-scheduling which is a basic building block in the modern OS. Time sharing creates the illusion of simultaneous execution, allowing users to interact with multiple tasks concurrently. While multiprogramming focuses on CPU efficiency, multitasking emphasizes responsiveness and interactive user experiences. In multi-tasking systems, the CPU executes multiple jobs by switching among them rapidly, ensuring fair resource allocation and seamless user interaction.

Note: CPU-bound vs I/O-bound
Applications often consist of intensive CPU work, but they may also interact with I/O devices like keyboards, disks, or networks to read inputs or produce outputs.
CPU-bound
An application is CPU-bound if its performance primarily depends on CPU speed. Such applications would run faster with a more powerful CPU.
I/O-bound
An application is I/O-bound if its performance depends on the speed of I/O subsystems (e.g., disk, network). These applications benefit from faster I/O devices or optimized I/O operations.

Preemptive Multitasking

Preemptive multitasking allows the operating system to forcibly interrupt a running task to allocate CPU time to another task. This is typically achieved through time-slicing, where each task runs for a predefined interval before the OS preempts it. Preemption ensures fair CPU usage, prevents monopolization by a single task, and enhances system responsiveness. Modern operating systems (e.g., Windows, Linux) use this approach to manage multiple processes and threads efficiently.

Context Switching

Context switching is the process of saving the state (e.g., registers, program counter) of a running task and restoring the state of another task. While essential for multitasking, it introduces overhead as the CPU spends time managing switches rather than executing tasks. Optimizations like hardware-supported context switching and efficient scheduling algorithms minimize this overhead.

Cooperative Multitasking

In cooperative multitasking, tasks voluntarily yield control to the scheduler, allowing other tasks to run. The OS cannot forcibly preempt a task; instead, tasks must explicitly relinquish control (e.g., via yield() calls). This approach requires careful programming, as a misbehaving task that fails to yield can block the entire system. Cooperative multitasking was used in early systems like Windows 3.x and classic Mac OS. It is also prevalent in runtime environments for asynchronous programming (e.g., Python’s asyncio, JavaScript’s event loop).

Multitasking OSs

Task Isolation

Task isolation ensures that tasks operate independently without interfering with each other. Modern OSs achieve this through virtual memory, memory protection, and separate address spaces. For example, processes run in isolated memory spaces, while threads within a process share memory but synchronize access to avoid concurrency issues. Isolation enhances security and stability, preventing crashes in one task from affecting others.

Task Scheduling (CPU Scheduling)

Task scheduling determines how the OS allocates CPU time to tasks. Common algorithms include:

  • Round Robin: Tasks execute in fixed time slices.
  • Priority-Based: Higher-priority tasks run first.
  • Shortest Job Next (SJN): Prioritizes tasks with the smallest execution time. Modern schedulers dynamically adjust priorities and use hybrid strategies to optimize throughput, latency, and fairness.

Conclusion

Multi-tasking is foundational to modern computing, enabling concurrent execution of tasks through preemptive or cooperative strategies. Preemptive multitasking, driven by time-slicing and context switching, ensures responsiveness and fairness in general-purpose OSs. Cooperative multitasking, while less common today, remains relevant in specific asynchronous programming paradigms. Understanding CPU-bound vs I/O-bound tasks helps optimize performance, while advancements in task isolation and scheduling continue to enhance system efficiency and reliability.