• Operating System Video Tutorials

Operating System - Mutex



In multitasking programming, mutex locks, or mutual exclusion locks, are fundamental synchronization mechanisms used to prevent simultaneous possession of shred resources by multiple threads or processes. The term "mutex" stands for "mutual exclusion".

What are Mutex Locks?

A mutex lock enables mutual exclusion by limiting the number of threads or processes that can simultaneously acquire the lock. A thread or process that can simultaneously acquire the lock.

A thread or process must first obtain the mutex lock for a shared resource before accessing it. If the lock is held by another thread or process, the requesting thread or process is halted and placed in a waiting state until the lock becomes available. Once the lock is acquired, the thread or process can access the shared resource. Upon completion, it releases the lock, allowing other threads or process to acquire it.

Components of Mutex Locks

The main components of Mutex Locks are discussed below.

  • Mutex Variable: A mutex variable represents the lock. It is a data structure that maintains the lock's state and allows threads or processes to acquire and release it.

  • Lock Acquisition: Threads or processes can request the lock. If the lock is available, the requesting thread or process gains ownership of it. Otherwise, it enters a waiting state until the lock becomes available.

  • Lock Release Once a thread or process has finished using the shared resource, it releases the lock, allowing other threads or processes to acquire it.

Types of Mutex Locks

Mutex locks come in various forms, each offering different levels of capabilities and behavior. Below are a few commonly used types of mutex locks:

Recursive Mutex

A recursive mutex allows multiple lock acquisitions without blocking a thread or process. It tracks the number of times it was acquired and requires the same number of releases before it can be fully unlocked.

For Example

Consider a data framework with a tree-like directory structure. Each node in the tree represents a directory, and several threads are simultaneously traversing the tree to perform various operations.

The use of a recursive mutex can prevent conflicts. A thread is a program that navigates through a directory node, acquires the lock, performs its actions, and then re-enters to access subdirectories. The recursive mutex allows multiple acquisitions of the same lock without blocking the thread, ensuring proper traversal and synchronization.

Error-Checking Mutex

An error-checking mutex performs additional error checking when acquiring a lock. By preventing recursive lock acquisition, it ensures that an application or process does not acquire a mutex lock it already holds.

For Example

Consider a multi-threaded program in which multiple processes update a common counter variable. The counter is protected by a mutex lock to avoid conflicts and race conditions.

An error occurs if a thread unintentionally tries to acquire the mutex lock it already holds. Thanks to the error-checking mutex, such coding errors can be detected and quickly corrected by programmers.

Times Mutex

An algorithm or process can attempt to acquire a lock for a predetermined amount of time using a timed mutex. If the lock does not become available within the allotted time, the acquisition attempt fails, allowing the thread or process to respond accordingly.

For Example

Consider a real-time system with multiple operations or threads that need access to a limited number of fixed resources. Each task requires a specific resource within a certain period, it may need to take an alternative action or indicate an error. By using a timed mutex, each task can attempt to acquire the resource for a set amount of time. If the resource is not available within the allotted time, the task can proceed with an alternative method or take the appropriate action based on the limit situation.

Priority Inheritance Mutex

A priority inheritance mutex(also known as a priority ceiling mutex) helps reduce priority inversion issues. It temporarily elevates the priority of the low-priority thread or process holding the lock to the level of the highest-priority thread or process waiting for the lock to be released. This ensures that the low-priority thread or process can complete its task and release the lock, allowing the higher-priority thread or process to proceed.

For Example

Consider a real-time system with several thread operating at various priorities. These processes have access to shared resources protected by mutex can be used to avoid priority thread blocks a higher-priority thread gains immediate access to the resource, the mutex temporarily raises the priority of the lower-priority thread to match that of the highest-priority thread waiting for the lock.

Read-Write Mutex

A read-write lock is a synchronization mechanism that allows multiple threads or processes to access the same resource concurrently during read operations while ensuring mutual exclusion during write operations while ensuring mutual exclusion during write operations. Although it shares some similarities with mutex locks, it is not exclusively a type of mutex lock.

For Example

In a real-time online video implementation, only one thread is responsible for writing new frames into buffer, while multiple threads read from it. A read-write lock can be used to allow simultaneous reading threads can concurrently acquire the read lock for unrestricted access to the data structures. However, the writing thread obtains the write lock only when it need to modify the data, ensuring that no other threads can read or write during the update process.

Use Cases of Mutex Locks

We will now talk about some of the use cases of Mutex Locks.

  • Shared Resource Protection: Mutex locks are commonly used to protect shared resources in multi-threaded or multi-process environments. They ensure that only one thread or process can access the shared resource at a time, preventing data corruption and race conditions.

  • Critical Sections: Mutex locks are used to define critical sections in a program, ensuring that only one thread at a time can execute the code within the critical section. This preserves the integrity of shared data and prevents concurrent access issues.

  • Synchronization: Mutex locks enable synchronization between threads or processes, allowing them to coordinate their actions and access shared resources in a controlled manner. They ensure that certain operations are performed atomically, avoiding conflicts and maintaining consistency.

  • Deadlock Avoidance: Mutex locks can prevent deadlock situations where multiple threads or processes wait indefinitely for resources held by each other. By following proper locking protocols and avoiding circular dependencies, deadlocks situations can be avoided.

Implementation of Mutex Locks

In this example, multiple threads are created to increment a shared resource (shared_resource) by 1. The critical section where the shared resource is modified is protected by a mutex lock (mutex).

Each thread acquires the lock before entering the critical section and releases it after completing the critical section. The mutex lock ensures that only one thread can modify the shared resource at a time, preventing race conditions and ensuring the correctness of the final result.

import threading  

# Shared resource
shared_resource = 0

# Mutex lock
mutex = threading.Lock()

# Function to increment the shared resource
def increment():
   global shared_resource
   for _ in range(100000):
      # Acquire the lock
      mutex.acquire()
        
      # Critical section
      shared_resource += 1
        
      # Release the lock
      mutex.release()

# Create multiple threads
threads = []
for _ in range(5):
   thread = threading.Thread(target=increment)
   threads.append(thread)
# Start the threads
for thread in threads:
   thread.start()

# Wait for all threads to complete
for thread in threads:
   thread.join()

# Print the final value of the shared resource
print("Shared Resource:", shared_resource)

The result is obtained as follows −

Shared Resource: 500000

Benefits of Mutex Locks

Mutex locks benefit multitasking in a number of ways

  • Mutual Exclusion: Mutex locks ensure that only one thread or process can hold the lock at a time, preventing race conditions and ensuring predictable behavior in multi-threaded or multi-process scenarios.

  • Synchronization: Mutex locks enable programs and threads to coordinate access to shared resources, preventing unauthorized access and ensuring controlled access when an application or process attempts to acquire a locked mutex.

  • Simple and Portable: Mutex locks are widely supported in various programming languages and OS platforms and are relatively easy to use.

  • Efficiency: Mutex locks are generally when there is little contention as they generate minimal overhead when the lock is not being contested.

Drawbacks of Mutex Locks

Mutex locks have several drawbacks when it comes to multitasking −

  • Potential Deadlocks: Improper use of mutex locks can lead to deadlocks, where multiple threads or processes are indefinitely blocked, waiting for locks that will never be released.

  • Priority Inversion: Priority inversion can occur when a high-priority thread or process is blocked, waiting for a lock held by a lower-priority thread or process.

  • Resource Utilization: Mutex locks can lead to poor resource utilization if threads or processes are frequently blocked while waiting for locks.

Conclusion

In summary, mutex locks are useful for synchronizing basic functions in concurrent programming. By allowing only one thread or process to access a shared resource at a time, they ensure mutual exclusion, synchronization, and help prevent race conditions. Mutex locks provide a standardization, are easy to use, and are widely accepted.

Advertisements