Monitors
I am Jyotiprakash, a deeply driven computer systems engineer, software developer, teacher, and philosopher. With a decade of professional experience, I have contributed to various cutting-edge software products in network security, mobile apps, and healthcare software at renowned companies like Oracle, Yahoo, and Epic. My academic journey has taken me to prestigious institutions such as the University of Wisconsin-Madison and BITS Pilani in India, where I consistently ranked among the top of my class.
At my core, I am a computer enthusiast with a profound interest in understanding the intricacies of computer programming. My skills are not limited to application programming in Java; I have also delved deeply into computer hardware, learning about various architectures, low-level assembly programming, Linux kernel implementation, and writing device drivers. The contributions of Linus Torvalds, Ken Thompson, and Dennis Ritchie—who revolutionized the computer industry—inspire me. I believe that real contributions to computer science are made by mastering all levels of abstraction and understanding systems inside out.
In addition to my professional pursuits, I am passionate about teaching and sharing knowledge. I have spent two years as a teaching assistant at UW Madison, where I taught complex concepts in operating systems, computer graphics, and data structures to both graduate and undergraduate students. Currently, I am an assistant professor at KIIT, Bhubaneswar, where I continue to teach computer science to undergraduate and graduate students. I am also working on writing a few free books on systems programming, as I believe in freely sharing knowledge to empower others.
Monitors, in the context of synchronization, are high-level synchronization constructs used in concurrent programming. They provide a mechanism to control access to shared resources by multiple threads in a concurrent system. Here's a basic overview of their components and operations:
Initialization Code: This is where the shared resource and its initial state are defined. Also, any necessary synchronization primitives (like locks) are initialized here.
Procedures: These are methods or functions that operate on the shared resource. They typically begin by acquiring a lock to ensure exclusive access to the resource and end by releasing the lock.
Entry Queue: This is a queue of processes that are waiting to enter the monitor to execute one of its procedures. A process is placed in this queue if it attempts to execute a procedure while another process is already executing a procedure within the monitor. The constraints are such that at any given time, only one process can be executing any of the monitor's procedures.
Condition Variables: These are used for waiting inside a monitor's procedure when some condition is not met (like waiting for a resource to become available). They help in organizing the waiting processes into different queues based on different conditions.
Condition Variable Queues: Each condition variable has its own queue. A process that finds the condition it's waiting for is not met, it can wait on a condition variable, which effectively places it in the condition variable's queue. This is separate from the entry queue for the monitor itself.
Operations on Condition Variables: The primary operations are
wait,signal, andbroadcast.wait: This operation causes the calling process to block and be placed in the condition variable's queue. Before blocking, it releases the lock on the monitor, allowing other processes to enter.signal: This operation wakes up one of the processes waiting in the condition variable's queue (if any). The signaling process usually continues its execution and releases the monitor's lock at some point afterward, allowing the woken process to acquire the lock and resume execution.broadcast: Similar tosignal, but wakes up all processes waiting on the condition variable.
Here's a simple pseudo-code to illustrate these concepts:
monitor MyMonitor
// Shared resource
resource_type shared_resource
// Initialization
initialize() {
shared_resource = initial_value
}
// Condition variables
condition_variable cv1, cv2
// Procedure 1
procedure_1() {
acquire_lock()
while (not condition_for_procedure_1)
cv1.wait()
// Operate on shared_resource
release_lock()
}
// Procedure 2
procedure_2() {
acquire_lock()
while (not condition_for_procedure_2)
cv2.wait()
// Operate on shared_resource
if (new_condition_met)
cv1.signal() // or cv1.broadcast()
release_lock()
}
end monitor
In this pseudo-code, acquire_lock() and release_lock() are implicit in entering and leaving the monitor's procedures. The wait operation on a condition variable automatically releases the lock, and re-acquires it upon returning from the wait. The signal or broadcast operations are used to notify other threads waiting on a condition variable that they might proceed if the condition they are waiting for is potentially met.