Tuesday, August 5, 2025

CST334: Week 6 (Week 30)

This week we continued learning about concurrency. We learned about atomicity, semaphores, signaling, condition variables, and some of the pitfalls of multithreaded implementations like deadlocks, starvation, livelocks, etc.

We learned that semaphores are better suited for signaling between threads vs resource locking like mutexes. A semaphore represents an integer value but that is incremented or decremented via atomic operations. It is initialized to some integer value specified by the programmer. For example, a software interface for a device with N transmit queues may use a semaphore initialized to N. Each time a process thread successfully requests a queue, the semaphore is decremented, until it reaches 0. At that point, future requesters must wait. When a thread is done transmitting, it increments the semaphore, thus signaling waiting threads that a queue is available. The behavior seems similar to mutexes but mutexes are better suited to protecting a shared resource in a critical section than they are for signaling.

It's interesting that for semaphores and mutexes to work, the instruction set has to implement an atomic read-modify-write operation. Otherwise, the lock/unlock or increment/decrement operations may be interrupted before they complete. It just shows how specific some of the instruction set needs to be to provide the higher level features we take for granted.

We also learned how to use condition variables that allow waiting threads to be notified when a condition is met. For example, a condition variable may be used to notify thread that a buffer is empty so that it can step out of it end its wait loop and lock the buffer, before before queueing new buffer entries.

We also learned about the risks that come with multithreaded programing like deadlocks, starvation, livelock, etc. When we are dealing with a lot of shared resources and many actors contending for access it's easy to imagine how things can go wrong. Circular dependencies, ill-conceived priority + preemption algorithms, and other failings can wreak havoc. That's why we were also shown design patterns that use locks, semaphores, and condition variables in ways that help avoid some of the pitfalls.

I have a lot of respect for the researchers and engineers who devise these techniques.

No comments:

Post a Comment

CST370: Week 7 (Week 58)

 This week we covered non-comparison sorting, dynamic programming, Warshall's algorithm, Floyd's algorithm, Greedy Technique, and Pr...