DEV Community

ivinieon
ivinieon

Posted on

How is the monitor used for synchronization?

Monitor

  • Ensures mutual exclusion
  • Allows threads to wait based on conditions

When is it used?

  • When only one thread should be executing at a time
  • When collaboration between multiple threads is needed

Components of the monitor

- Mutex: A device that ensures mutual exclusion in critical sections. A thread must acquire a mutex lock to enter a critical section. If a thread cannot acquire the mutex lock, it goes into a waiting state in the queue. When a thread holding the mutex lock releases it, one of the waiting threads in the queue is selected to execute.

- Condition variables: Have a waiting queue. Where threads wait for a condition to be met in a waiting state.

Operations on condition variables:

  • wait: The thread puts itself in the waiting queue of the condition variable and goes into a waiting state.
  • signal: Wakes up one of the threads waiting in the waiting queue.
  • broadcast: Wakes up all threads waiting in the waiting queue.
acquire(m) // Acquire the lock of the monitor
while(!p) { // Check the condition
    wait(m, cv); // If the condition is not met, wait
}
...
signal(cv2); --OR-- broadcast(cv2); //cv2 can be the same as cv
release(m); // Release the lock of the monitor

Enter fullscreen mode Exit fullscreen mode

When a thread enters the waiting queue, it must release the lock.

Two queues

- Entry queue: The queue of threads waiting to enter the critical section. Managed by the mutex.
- Waiting queue: The queue of threads waiting for a condition to be met. Managed by the condition variable.

Bounded producer/consumer problem:

The producer creates goods and fills them in a buffer, while the consumer consumes the goods.

Problem scenario 1: The producer keeps creating goods, but the buffer is full and there is no room left.

Problem scenario 2: The consumer tries to consume goods, but the buffer is empty and there is nothing to consume.

global volatile Buffer q;
global Lock lock;
global CV fullCV;
global CV emptyCV;
-------------------------------------------------------
public method producer() {
    while(true) {
        task myTask = ...'

        lock.acquire(); 
        // A mutex lock is required to enter the CV. If there is no lock, enter the entry queue and wait.

        while(q.isFull()) {
            wait(lock, fullCV); // Check if the buffer is full. If it is full, wait in the waiting queue.
        }

        q.enqueue(myTask);

        signal(emptyCV); --or-- broadcast(emptyCV);

        lock.release();
        }
    }

--------------------------------------------------------

public method consumer() {
    while(true) {
        lock.acquire();
        // The producer and consumer compete for one lock.
        while(q.isEmpty()) {{
            wait(lock, emptyCV);
        } // Always wait in the while loop so that when awakened, it can check if the condition is met.
            // If the buffer is empty, wait in the waiting queue.
        myTask = q.dequeue();

        signal(fullCV); --or-- broadcast(fullCV);

        lock.release();

        doStuff(myTask);
    }
}

Enter fullscreen mode Exit fullscreen mode

What is a Java monitor?

In Java, every object has an internal monitor.

The mutual exclusion functionality of the monitor is used with the synchronized keyword.

Java monitors have only one condition variable.

Three operations of the Java monitor:

  • wait
  • notify(signal)
  • notifyAll(broadcast)

This posting is just a study note which was written after watching youtube videos in Korean.
https://youtu.be/Dms1oBmRAlo

Top comments (0)