
Understanding Atomicity, Mutex, and Locks in Operating Systems
Explore the concepts of atomicity, mutex, and locks in operating systems to manage critical sections effectively, prevent race conditions, and ensure mutual exclusion for concurrent processes. Learn about implementing locks, avoiding race conditions, atomic operations, and more.
Download Presentation

Please find below an Image/Link to download the presentation.
The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.
You are allowed to download the files provided on this website for personal or commercial use, subject to the condition that they are used lawfully. All files are the property of their respective owners.
The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author.
E N D
Presentation Transcript
Atomicity, Mutex, and Locks David Ferry CSCI 3500 Operating Systems Saint Louis University St. Louis, MO 63103 1
Critical Sections Recall the problem with race conditions: Suppose x=0 initially: Thread 1 u = x u = u + 1 x = u Thread 2 v = x v = v * 2 x = v A critical section is any piece of code that should not execute simultaneously with another piece of code. CSCI 3500 - Operating Systems 2
Critical Sections Recall the problem with race conditions: Suppose x=0 initially: Thread 1 u = x u = u + 1 x = u Thread 2 v = x v = v * 2 x = v A critical section is any piece of code that should not execute simultaneously with another piece of code (potentially itself- see push() from last time). CSCI 3500 - Operating Systems 3
Locks & Mutex (Mutual Exclusion) We need to prevent simultaneous access to critical sections. Something like: mutex m; lock(m); unlock(m); //Do critical section Where lock(m): Proceeds if m is unlocked If not, blocks until m is unlocked CSCI 3500 - Operating Systems 4
Implementing lock() and unlock()? lock() should block until the mutex variable is unlocked, a na ve implementation: int mutex = 0; lock( mutex ): while(1){ if( mutex == 0 ){ mutex = 1; break; } } unlock( mutex ): mutex = 0; CSCI 3500 - Operating Systems 5
But wait Another race condition! lock( mutex ) translates to: while(1){ if( mutex == 0 ){ load m to register mutex = 1; break; } } start: compare m jump if not zero->start store 1 to memory What if we could simultaneously test and update the value of the mutex variable? CSCI 3500 - Operating Systems 6
Atomic Operations An atomic operation is one that is indivisible. From the previous slide, what we want is this: if ( m == 0 ) //Test the value of m m = 1; //Set the value of m If this were atomic, then it looks as though both statements execute simultaneously. The outside world sees the before or after but never any intermediate states. In particular, a second thread can t come along and read the value of m after it has already been read but before the assignment m=1 takes place. CSCI 3500 - Operating Systems 7
Hardware to the Rescue Hardware designers can give us a special atomic test and setinstruction. Then: lock(mutex): while(1){ int success = hardware_test_and_set(mutex); if( success ) break; } The lock() functions we use probably look something like this, modulo performance optimizations. CSCI 3500 - Operating Systems 8
Unsatisfying? Do we have to rely on hardware giving us a special solve everything instruction? In fact, mutual exclusion can be accomplished only with regular memory loads and stores (i.e. in software). The first such solution, Dekker s Algorithm, was published by Edsger Dijkstra in 1968. Leslie Lamport published the first general solution called the Bakery Algorithm in 1974. Other solutions exist since then. Hardware implementations tend to be faster and easier to implement. However, software-only solutions can be useful, such as when portability is important. CSCI 3500 - Operating Systems 9
Other Atomic Operations We will see other atomic operations in the studios. E.g.: __sync_fetch_and_add(); This function synchronously (atomically) loads a value from memory and adds to it. Thread 1: x++; Thread 2: x++; CSCI 3500 - Operating Systems 10
Solving Race Conditions Critical sections occur when variables are shared between threads, in particular when shared variables are written to. lock() and unlock(): Can encapsulate any critical section Code/data can be any size Atomic operations: Usually faster, if applicable CSCI 3500 - Operating Systems 11