JavaRush /Java Blog /Random EN /What is the difference between mutex, monitor and semapho...

What is the difference between mutex, monitor and semaphore

Published in the Random EN group
Hello! Studying multithreading on CodeGym, you often came across the concepts of "mutex" and "monitor". Can you now, without peeping, answer how they differ? :) What is the difference between mutex, monitor and semaphore - Stack OverflowIf I could - well done! If not (and most often it happens) - no wonder. The concepts of "mutex" and "monitor" are indeed related. Moreover, reading lectures and watching videos on multithreading on external resources on the Internet, you will come across another similar concept - “semaphore”. Its functionality is also largely similar to the monitor and mutex. Therefore, we will deal with these three terms, consider a few examples and finally arrange in our head the understanding of how they differ from each other :)

Mutex

A mutex is a special object for thread synchronization. It is "attached" to every object in Java - you already know that :) It doesn't matter if you use standard classes or create your own classes, say, Catand Dog: all objects of all classes have a mutex . The name "mutex" comes from the English "MUTual EXclusion" - "mutual exclusion", and this perfectly reflects its purpose. As we said in one of the previous lectures, the task of a mutex is to provide such a mechanism that only one thread has access to an object at a certain time.. A popular analogy for a mutex in real life is the "toilet example". When a person enters the toilet, he closes the door from the inside with a lock. The toilet acts as an object that can be accessed by multiple threads. The lock on the toilet door is the role of the mutex, and the line of people outside is the role of the threads. The lock on the door is the mutex of the toilet: it ensures that only one person can be inside at a time. What is the difference between mutex, monitor and semaphore - Stack OverflowIn other words, only one thread at a time can access shared resources. Attempts by other threads (people) to access busy resources will fail. A mutex has several important features. First , only two states are possible - "free" and "busy". This simplifies the understanding of the principle of operation: you can draw parallels with boolean variablestrue/false or binary number system 1/0. Second , states cannot be manipulated directly. There are no mechanisms in Java that would allow you to explicitly take an object, get its mutex and assign it the desired status. In other words, you can't do something like:
Object myObject = new Object();
Mutex mutex = myObject.getMutex();
mutex.free();
Therefore, the mutex of an object cannot be released. Only the Java machine has direct access to it. Programmers work with mutexes using language tools.

Monitor

The monitor is an additional "add-on" over the mutex. In fact, the monitor is a piece of code "invisible" to the programmer . Speaking about the mutex earlier, we gave a simple example:
public class Main {

   private Object obj = new Object();

   public void doSomething() {

       //...some logic available to all threads

       synchronized (obj) {

           //logic that is only available to one thread at a time
       }
   }
}
In the block of code, which is marked with the word synchronized, the mutex of our object is captured obj. Okay, capture is happening, but how exactly is the "defense mechanism" provided? synchronizedWhy can't other threads go inside the block when they see a word ? It is the monitor that creates the protective mechanism! The compiler converts the word synchronizedinto several special pieces of code. Let's go back to our example with the method doSomething()and add it:
public class Main {

   private Object obj = new Object();

   public void doSomething() {

       //...some logic available to all threads

       //logic that is only available to one thread at a time
       synchronized (obj) {

           /*выполнить важную работу, при которой доступ к an objectу
           должен быть только у одного потока*/
           obj.someImportantMethod();
       }
   }
}
Here is what will happen "under the hood" of our program after the compiler transforms this code:
public class Main {

   private Object obj = new Object();

   public void doSomething() throws InterruptedException {

       //...some logic available to all threads

       //логика, которая одновременно доступна только для одного потока:

       /*до тех пор, пока мьютекс an object занят -
       любой другой поток (кроме того, который его захватил), спит*/
       while (obj.getMutex().isBusy()) {
           Thread.sleep(1);
       }

       //пометить мьютекс an object How занятый
       obj.getMutex().isBusy() = true;

       /*выполнить важную работу, при которой доступ к an objectу
       должен быть только у одного потока*/
       obj.someImportantMethod();

       //освободить мьютекс an object
       obj.getMutex().isBusy() = false;
   }
}
The example is not real, of course. Here, using Java-like code, we tried to reflect what is happening at this moment inside the Java machine. However, this pseudocode gives a great understanding of what is actually happening with the object and threads inside the block, synchronizedand how the compiler translates this word into a few "invisible" instructions for the programmer. Essentially, a monitor in Java is expressed using the wordsynchronized . All the code that appeared instead of a word synchronizedin the last example is the monitor.

Semaphore

Another word that you come across when learning multithreading on your own is “semaphore”. Let's see what it is, and how it differs from a monitor and a mutex. A semaphore is a means for synchronizing access to some resource. Its peculiarity lies in the fact that when creating a synchronization mechanism, it uses a counter. The counter tells us how many threads can access the shared resource at the same time. What is the difference between mutex, monitor and semaphore - Stack OverflowSemaphores in Java are represented by the Semaphore. When creating semaphore objects, we can use the following constructors:
Semaphore(int permits)
Semaphore(int permits, boolean fair)
We pass to the constructor:
  • int permits— the initial and maximum value of the counter. That is, how many threads can simultaneously access a shared resource;

  • boolean fair- to establish the order in which threads will access. If fair= true , access is granted to waiting threads in the order in which they requested it. If it is false , the order will be determined by the thread scheduler.

A classic example of the use of semaphores is the Dining Philosophers Problem .
What is the difference between mutex, monitor and semaphore - Stack Overflow
We will simplify its conditions a little, for a better understanding. Imagine that we have 5 philosophers who need to have lunch. At the same time, we have one table, and no more than two people can be at it at the same time. Our task is to feed all philosophers. None of them should go hungry, nor should they "block" each other when they try to sit down at the table (we should avoid deadlock). This is what our philosopher class will look like:
class Philosopher extends Thread {

   private Semaphore sem;

   // поел ли философ
   private boolean full = false;

   private String name;

   Philosopher(Semaphore sem, String name) {
       this.sem=sem;
       this.name=name;
   }

   public void run()
   {
       try
       {
           // если философ еще не ел
           if (!full) {
               //Запрашиваем у семафора разрешение на выполнение
               sem.acquire();
               System.out.println (name + " садится за стол");

               // философ ест
               sleep(300);
               full = true;

               System.out.println (name + " поел! Он выходит из-за стола");
               sem.release();

               // философ ушел, освободив место другим
               sleep(300);
           }
       }
       catch(InterruptedException e) {
           System.out.println ("What-то пошло не так!");
       }
   }
}
And here is the code to run our program:
public class Main {

   public static void main(String[] args) {

       Semaphore sem = new Semaphore(2);
       new Philosopher(sem,"Сократ").start();
       new Philosopher(sem,"Платон").start();
       new Philosopher(sem,"Аристотель").start();
       new Philosopher(sem,"Фалес").start();
       new Philosopher(sem,"Пифагор").start();
   }
}
We created a semaphore with a count of 2 to meet the condition that only two philosophers can eat at a time. That is, only two threads can work at the same time, because our class Philosopheris inherited from Thread! Methods acquire()and release()classes Semaphoremanage its permission count. The method acquire()requests permission to access the resource from the semaphore. If the counter is > 0, the permission is granted and the counter is decremented by 1. The method release()"releases" the previously granted permission and returns it to the counter (increments the semaphore's permission counter by 1). What will we get when we run the program? Is the problem solved, will our philosophers not fight, waiting for their turn? :) Here is the console output we got: Socrates sits down at the table Plato sits down at the table Socrates ate! He leaves the table Plato ate! He leaves the table Aristotle sits down at the table Pythagoras sits down at the table Aristotle has eaten! He leaves the table. Pythagoras has eaten! He leaves the table Thales sits at the table Thales has eaten! He leaves the table We did it! And although Thales had to dine alone, I think he is not offended by us :) You might notice some similarities between a mutex and a semaphore. They have, in general, the same purpose: to synchronize access to some resource. What is the difference between mutex, monitor and semaphore - Stack OverflowThe only difference is that the mutex of an object can be captured by only one thread at a time, and in the case of a semaphore, a thread counter is used, and several of them can access the resource at once. And this is not just an accidental similarity :) In fact, a mutex is a single-place semaphore . That is, it is a semaphore whose counter is initially set to 1. It is also called a "binary semaphore", since its counter can only have 2 values ​​- 1 ("free") and 0 ("busy"). That's all! As you can see, everything turned out to be not so confusing :) Now, if you want to study the topic of multithreading in more detail on the Internet, it will be a little easier for you to navigate the concepts. See you in the next lessons!
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION