Week 5 – CST– 334 Operating System
Module 5 – Concurrency Introduction
This week we covered an introduction to concurrency.
So far, we have studied single threaded programs. Programs can also have
multiple threads of execution. A process for example, can fork a child but
parent and child do not share memory because they have their own copies of code
and data in memory. A process can also create multiple threads which share the
same address space and can use global variables to communicate which use less
memory. Each thread has its own program counter and stack.
The advantage of using threads is parallelism, this means that a single process
can use multiple CPU cores in parallel to complete tasks. The disadvantage when
using threads comes in the form of a race condition. A race condition happens
when multiple threads access a section of code that has shared variables. These
sections of code are called critical sections. Multiple threads entering this
section causes unpredictable results. In order to avoid race conditions,
programmers must use locks to protect critical sections.
Locks are meant to allow only one thread at a time to access a critical
section. Once done, the thread gives up the lock and another thread will hold
the lock to gain access into the critical section. While a thread has a lock in
a critical section, other threads can spin until the lock becomes available.
Spinning means the thread is stuck in a while loop until the lock is released.
Spinning is considered inefficient because the thread wastes an entire time
slice just checking a value that indicates whether the lock is available. Other
alternatives threads can use are wait, sleep, or yield the CPU which moves the
thread from a running state to the ready state.
Lastly, we learned about condition variables wait and signal. These are used in
situations where a thread wishes to check whether a condition is true before
continuing its execution. The text explains condition variables with the
producer/ consumer problem. A problem where producers produce data items and
put them on a buffer. Consumers grab the data items from the buffer to consume
them. The producer threads wait on the condition empty, and signal fill when
they are done executing. The consumer threads wait on fill and signal empty
when done executing. This prevents threads from waking up the wrong type of
threads. An example of this problem is a multi-threaded web server. Producer
threads put HTTP requests into a work queue and consumer threads take the
requests out of the queue and process them.
Comments
Post a Comment