Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 1

Critical Sections and Race Conditions

Recommended resources

Hello! Welcome to the first lesson of our course on Operating System Synchronization and Deadlocks.

Given your background in computer science and your goal of preparing for the GATE exam, we'll dive straight into the core concepts, focusing on the theoretical underpinnings and problem-solving techniques that are essential for success. This first lesson lays the foundation for everything that follows. We will explore why we need synchronization in the first place by defining the critical section problem and learning to identify race conditions in concurrent programs.

Let's begin by understanding the context in which these problems arise.

1. Cooperative vs. Independent Processes

In a modern multitasking operating system, multiple processes can run concurrently. From a synchronization perspective, these processes can be divided into two main categories:

  • Independent Processes: The execution of one process does not affect and is not affected by the execution of other processes. They do not share any data.
  • Cooperative Processes: The execution of one process can affect or be affected by another. This happens because they share something, such as memory, a variable, a file, or a hardware resource.

Our focus throughout this course will be on cooperative processes, as their interaction is what creates the need for synchronization mechanisms.

To get a clear introduction to these concepts, please watch the first part of the following video from Gate Smashers.

L-3.1: Process Synchronization | Process Types | Race Condition | Operating System-1

This video introduces the fundamental concepts of process synchronization, explaining the difference between independent and cooperative processes and why synchronization is crucial for the latter.

Watch the segment from the beginning until 04:41. Focus on understanding why cooperative processes are the primary concern for synchronization due to shared resources.

As the video explains, when processes share data, the order in which they execute can lead to unexpected and incorrect outcomes. This brings us to a fundamental problem in concurrent programming: the race condition.


2. The Race Condition

A race condition is an undesirable situation that occurs when a device or system attempts to perform two or more operations at the same time, but because of the nature of the device or system, the operations must be done in the proper sequence to be done correctly.

In the context of operating systems, a race condition occurs when multiple processes access and manipulate the same shared data concurrently, and the final outcome depends on the particular order in which the access takes place. The "race" is among the processes to see who can access and change the data last.

A Concrete Example

Let's analyze the classic example of a race condition. Imagine two processes, P1 and P2, that both access a shared integer variable count, which is initially 5.

  • Process P1 executes count++.
  • Process P2 executes count--.

If these operations were atomic (indivisible), the final value of count would always be 5, regardless of which process runs first. However, these high-level operations are not atomic. At the machine level, they are typically broken down into three instructions:

  1. Load the value of count from memory into a register.
  2. Increment/decrement the value in the register.
  3. Store the new value from the register back into memory.

Now, consider what happens if the operating system switches context between these low-level instructions. The next video segment walks through this scenario in detail, showing how preemption can lead to an incorrect result.

L-3.1: Process Synchronization | Process Types | Race Condition | Operating System-1

This part of the video provides a step-by-step demonstration of how a race condition occurs. It shows how the interleaving of low-level instructions from two processes modifying a shared variable leads to data inconsistency.

Watch from 08:07 to 16:25. Pay close attention to how context switching between the load, modify, and store operations results in a final value of 4 or 6, instead of the expected 5.

Race Condition Illustration
This flowchart illustrates a race condition with a shared bank balance. P1 and P2 both read the initial balance of 100. P2 updates it to 90, but P1, working with the old value, overwrites it with 110, leading to an inconsistent state.

This unpredictability is the core of the problem. Your program might work correctly 99 times, but that one time the scheduler interleaves instructions in a specific "unlucky" way, the result is wrong. For the GATE exam, understanding how different interleavings produce different results is crucial.


3. The Critical Section Problem

To prevent race conditions, we need a way to ensure that when one process is manipulating shared data, no other process can interfere. The part of a program where a process accesses shared resources is called the critical section.

The critical section problem is to design a protocol that cooperative processes can use to synchronize their actions. Each process must request permission to enter its critical section. The section of code implementing this request is the entry section. The critical section may be followed by an exit section. The remaining code is the remainder section.

Critical Section Definition and Structure
A visual representation of a process's structure, divided into four key sections: the Entry Section to request access, the Critical Section for shared resource access, the Exit Section to release access, and the Remainder Section for non-critical code.

The challenge is to write the entry and exit sections to guarantee that only one process is in its critical section at any given time.

The next video defines the critical section and its surrounding structure.

L-3.4: Critical Section Problem | Mutual Exclusion, Progress and Bounded Waiting | Operating System

This video defines the critical section and introduces the general structure of a solution, which involves an entry section, the critical section itself, and an exit section.

Watch the first part of this video, from the beginning to 08:42. Focus on the definitions of the critical section, non-critical section, entry section, and exit section.


4. Requirements for a Valid Solution

Any valid solution to the critical section problem must satisfy three essential conditions. For GATE, these are very important to know by heart.

  1. Mutual Exclusion: If a process is executing in its critical section, then no other processes can be executing in their critical sections. This is the fundamental requirement.
  2. Progress: If no process is executing in its critical section and some processes wish to enter their critical sections, then the selection of the process that will enter the critical section next cannot be postponed indefinitely. This means there should be no deadlock among the processes trying to enter.
  3. Bounded Waiting: There must be a bound on the number of times that other processes are allowed to enter their critical sections after a process has made a request to enter its critical section and before that request is granted. This ensures that no process has to wait forever (starvation).

The video you just started watching also covers these three requirements in detail.

L-3.4: Critical Section Problem | Mutual Exclusion, Progress and Bounded Waiting | Operating System

Continuing with the same video, this segment explains the three mandatory requirements for any solution to the critical section problem: Mutual Exclusion, Progress, and Bounded Waiting.

Now, watch from 08:42 to 23:34. Make sure you can clearly distinguish between Progress (the system as a whole keeps moving) and Bounded Waiting (an individual process doesn't wait forever).

Test your understanding!

Consider a system with two processes, P1 and P2, competing for a critical section. A proposed solution has the following property: if P1 is interested in entering the critical section, P2 can enter and exit its own critical section at most 5 times before P1 is guaranteed to get access. Which of the three requirements does this property directly address?

Show answer

This property directly addresses Bounded Waiting. It places a finite limit (a bound of 5) on how many times P2 can "cut in line" after P1 has expressed interest, preventing starvation for P1.


5. GATE-Style Problem Analysis

Let's apply these concepts to a typical problem you might encounter. The key is to trace the possible interleavings of execution.

Process Synchronization | Race Condition in OS

The following article from Gate Vidyalay provides a concise summary of race conditions and a worked-out GATE-style problem. We will focus on the problem.

Scroll down to the 'PRACTICE PROBLEM BASED ON PROCESS SYNCHRONIZATION' section. First, read the problem description carefully. Before looking at the solution, try to determine the possible final values of the shared variable 'B' yourself by considering different execution orders.

Let's break down the problem from the article:

  • Shared variable B starts at 2.
  • Process P1: C = B - 1; B = 2 * C;
  • Process P2: D = 2 * B; B = D - 1;

Let's trace a few scenarios:

  • Scenario 1 (P1 then P2):

    1. C = B - 1 -> C = 2 - 1 = 1
    2. B = 2 * C -> B = 2 * 1 = 2
    3. D = 2 * B -> D = 2 * 2 = 4
    4. B = D - 1 -> B = 4 - 1 = 3
  • Scenario 2 (P2 then P1):

    1. D = 2 * B -> D = 2 * 2 = 4
    2. B = D - 1 -> B = 4 - 1 = 3
    3. C = B - 1 -> C = 3 - 1 = 2
    4. B = 2 * C -> B = 2 * 2 = 4
  • Scenario 3 (Interleaved):

    1. (P1) C = B - 1 -> C = 2 - 1 = 1 (P1 is preempted)
    2. (P2) D = 2 * B -> D = 2 * 2 = 4
    3. (P2) B = D - 1 -> B = 4 - 1 = 3 (P2 finishes)
    4. (P1) B = 2 * C -> B = 2 * 1 = 2 (P1 resumes and overwrites P2's work)

As the article's solution demonstrates, by exploring the different interleavings, we find the distinct possible values for B are 2, 3, and 4. The number of distinct values is 3.


Conclusion

In this lesson, we established the fundamental "why" of process synchronization. You learned that when concurrent, cooperative processes share resources, we can face unpredictable outcomes.

Key Takeaways:

  • Cooperative processes share data, which creates the potential for conflict.
  • A race condition occurs when the outcome of an operation depends on the non-deterministic scheduling order of concurrent processes.
  • The code segment where shared resources are accessed is the critical section.
  • The critical section problem is to design a protocol (entry/exit sections) that allows processes to cooperate safely.
  • Any valid solution must satisfy three conditions: Mutual Exclusion, Progress, and Bounded Waiting.

In our next lesson, we will begin exploring solutions to the critical section problem. We'll start with software-based solutions, specifically looking at Peterson's solution, a classic and elegant algorithm for two processes.