Process Synchronization in Operating System

Subject: Computer Science Fundamentals · Language: Operating System · Level: intermediate · 9 min read

Learn process synchronization with race condition, critical section, mutual exclusion, mutex, semaphore, and classic synchronization problems.

Process synchronization is a method used to coordinate processes or threads when they share data or resources. It makes sure that shared data is accessed in a controlled way so the final result remains correct. Synchronization becomes important when multiple processes or threads run concurrently. If they do not share data, synchronization may not be needed. But if they read and write the same variable, file, memory area, or device, then proper coordination is required.

For beginners, synchronization can be understood as traffic control. If many vehicles enter a narrow bridge at the same time without rules, accidents may happen. In the same way, if many threads access shared data without rules, incorrect results may happen.

Why Synchronization Is Needed

Synchronization is needed because process execution order is not always predictable. The OS scheduler can pause and resume processes at different times. A process may be interrupted in the middle of updating shared data. For example, suppose two threads increase the same counter. The counter value is 5. Both threads read 5, both add 1, and both write 6. The correct final value should be 7, but because of timing, the final value becomes 6. This is a synchronization problem. Synchronization prevents these mistakes by making sure that only one process or thread accesses important shared data at a time when required.

Race Condition

A race condition occurs when the final result depends on the order or timing of process execution. If different execution timing gives different results, there is a race condition. Race conditions are dangerous because they may not happen every time. A program may run correctly many times and then fail suddenly when the timing changes. This makes race condition bugs difficult to find. A common example is a shared bank account. If two transactions withdraw money at the same time without synchronization, both may read the old balance and update it incorrectly. The final balance may become wrong.

Shared Data

Shared data is any data that can be accessed by more than one process or thread. It may be a variable, file, memory location, database record, queue, or device state. Shared data is not always a problem. Reading shared data at the same time is often safe if no one is modifying it. Problems usually occur when at least one process writes or updates the shared data. When shared data can be modified, the OS or program must use synchronization techniques to protect it.

Critical Section

A critical section is the part of a program where shared data or shared resources are accessed. Since this part can affect correctness, it must be protected. Only one process or thread should execute the critical section at a time when the shared resource cannot be safely used by multiple processes together. This rule prevents race conditions. For example, the code that updates a shared counter is a critical section. The code that modifies a shared bank account balance is also a critical section.

Critical Section Problem

The critical section problem is the problem of designing a protocol that allows processes to access shared data safely. A correct solution should satisfy mutual exclusion, progress, and bounded waiting. Mutual exclusion means only one process can be inside the critical section at a time. This is the most basic requirement.

Progress means if no process is in the critical section, and some processes want to enter, the decision about who enters next should not be delayed forever. Bounded waiting means a process should not wait forever to enter the critical section. There should be a limit on how many times other processes can enter before it gets a chance.

Mutual Exclusion

Mutual exclusion means preventing multiple processes from entering the critical section at the same time. It protects shared data from simultaneous modification. A simple real-life example is a single bathroom key. Only the person holding the key can enter. Others must wait. In a computer system, locks, mutexes, and semaphores are used for similar control.

Lock

A lock is a synchronization tool used to control access to a critical section. Before entering the critical section, a thread tries to acquire the lock. After finishing, it releases the lock. If another thread already holds the lock, the current thread must wait. This ensures that only one thread enters the protected section at a time. Locks are simple to understand, but they must be used carefully. If a thread forgets to release a lock, other threads may wait forever.

Mutex

A mutex, or mutual exclusion lock, is used when only one thread should access a resource at a time. A mutex has two main operations: lock and unlock. When a thread locks a mutex successfully, it enters the critical section. Other threads trying to lock the same mutex must wait. When the thread finishes, it unlocks the mutex so another thread can enter. Mutexes are commonly used in multithreaded programs to protect shared variables, lists, files, or data structures.

Semaphore

A semaphore is a synchronization tool that uses an integer value to control access to resources. It supports two main operations often called wait and signal. The wait operation decreases the semaphore value. If the value is not available, the process may wait. The signal operation increases the semaphore value and may wake up a waiting process. A binary semaphore has only two states, usually 0 and 1. It can behave like a mutex. A counting semaphore can allow access to multiple instances of a resource, such as three printers or five database connections.

Mutex vs Semaphore

A mutex is mainly used for mutual exclusion, where only one thread should enter a critical section. A semaphore is more general and can manage one or more resource instances. A mutex is usually locked and unlocked by the same thread. A semaphore can be signaled by another process or thread depending on the design. For beginners, remember this simple idea: use a mutex to protect one critical section, and use a counting semaphore to manage multiple available copies of a resource.

Busy Waiting

Busy waiting happens when a process keeps checking repeatedly whether it can enter the critical section. It stays active and wastes CPU time while waiting. For example, a thread may keep checking a lock in a loop until the lock becomes free. This can be inefficient because the CPU is used only for repeated checking. Some synchronization methods avoid busy waiting by blocking the waiting process and waking it later when the resource becomes available.

Producer Consumer Problem

The producer-consumer problem is a classic synchronization problem. A producer creates data and puts it into a buffer. A consumer removes data from the buffer and uses it. Synchronization is needed because the producer should not add data when the buffer is full, and the consumer should not remove data when the buffer is empty. Also, both should not modify the buffer incorrectly at the same time. This problem teaches the use of semaphores and mutexes for coordinating shared buffers.

Reader Writer Problem

The reader-writer problem deals with shared data that can be read by many readers but written by writers. Multiple readers can read at the same time if no writer is writing. But when a writer writes, no other reader or writer should access the data. This problem is common in databases and file systems. It teaches how synchronization can allow safe sharing while still improving performance.

Dining Philosophers Problem

The dining philosophers problem is a classic problem used to explain synchronization, deadlock, and resource sharing. Philosophers sit around a table and need two forks to eat. If each philosopher picks one fork and waits for another, everyone may wait forever. This problem helps students understand how poor resource allocation can lead to deadlock and why careful synchronization design is needed.

Synchronization and Deadlock

Synchronization tools solve race conditions, but incorrect use of them can create deadlock. For example, if two threads acquire locks in different orders, each may wait for the other forever. This is why synchronization must be designed carefully. The goal is to protect shared data without causing unnecessary waiting or deadlock.

Summary

Process synchronization coordinates processes and threads that share data or resources. It prevents race conditions and protects critical sections. The most important beginner concepts are shared data, race condition, critical section, mutual exclusion, lock, mutex, semaphore, busy waiting, producer-consumer problem, reader-writer problem, and dining philosophers problem. These ideas are necessary before studying deadlock in detail.

More Operating System Lessons

Browse all PrepCampus study materials