CodeGym /Java блог /Случаен /Разлика между Mutex, Monitor и Semaphore
John Squirrels
Ниво
San Francisco

Разлика между Mutex, Monitor и Semaphore

Публикувано в групата
здрасти Когато сте изучавали многопоточност в CodeGym, често сте срещали понятията „мутекс“ и „монитор“. Без да надничате, можете ли да кажете How се различават? :) Ако да, браво! Ако не (това е най-често), това не е изненада. „Мутекс“ и „монитор“ всъщност са свързани понятия. Освен това, когато четете уроци и гледате видеоклипове за многопоточност на други уебсайтове, ще срещнете друга подобна концепция: „семафор“. Освен това има много подобна функция на мониторите и мютексите. Ето защо ще проучим тези три термина. Ще разгледаме няколко примера и ще стигнем до окончателно разбиране How тези понятия се различават една от друга :)

Mutex

Mutex (or заключване) е специален механизъм за синхронизиране на нишки. Единият е "прикрепен" към всеки обект в Java — вече знаете това :) Няма meaning дали използвате стандартни класове or създавате свои собствени класове, напр. Котка и Куче : всички обекти от всички класове имат мютекс . Терминът "mutex" идва от "MUTual EXclusion", което идеално описва неговата цел. Както казахме в един от предишните ни уроци, mutex прави възможно да се гарантира, че само една нишка в даден момент има достъп до обекта. Популярен реален пример за mutex включва тоалетни. Когато човек влезе в тоалетна преграда, той заключва вратата отвътре. Тоалетната е като обект, който може да бъде достъпен от множество нишки. Ключалката на преградната врата е като мютекс, а редицата от хора отвън представлява нишки. Ключалката на вратата е мутекс на тоалетната: тя гарантира, че само един човек може да влезе вътре. Каква е разликата между мютекс, монитор и семафор?  - 2С други думи, само една нишка в даден момент може да работи със споделени ресурси. Опитите на други нишки (хора) да получат достъп до заетите ресурси ще бъдат неуспешни. Мутексът има няколко важни характеристики. Първо , възможни са само две състояния: „отключено“ и „заключено“. Това ни помага да разберем How работи: можете да правите паралели с булеви променливи (true/false) or двоични числа (0/1). , държавата не може да се контролира пряко. Java няма механизъм, който би ви позволил изрично да вземете обект, да получите неговия мютекс и да присвоите желания статус. С други думи, не можете да направите нещо като:

Object myObject = new Object();
Mutex mutex = myObject.getMutex();
mutex.free();
Това означава, че не можете да освободите mutex на обект. Само Java машината има директен достъп до него. Програмистите работят с мутекси чрез инструментите на езика.

Монитор

Мониторът е допълнителна "надстройка" над мютекс. Всъщност мониторът е част от codeа, който е "невидим" за програмиста. Когато говорихме за mutexes по-рано, дадохме прост пример:

public class Main {

   private Object obj = new Object();

   public void doSomething() {

       // ...some logic, available for all threads

       synchronized (obj) {

           // Logic available to just one thread at a time
       }
   }
}
В codeовия блок, маркиран с ключовата дума synchronized , се придобива mutex на нашия obj обект. Чудесно, можем да придобием ключалката, но How точно се осигурява "защитата"? Когато видим думата synchronized , Howво пречи на другите нишки да влязат в блока? Защитата идва от монитор! Компилаторът преобразува синхронизираната ключова дума в няколко специални части от code. Още веднъж, нека се върнем към нашия пример с метода doSomething() . Ще добавим към него:

public class Main {

   private Object obj = new Object();

   public void doSomething() {

       // ...some logic, available for all threads

       // Logic available to just one thread at a time
       synchronized (obj) {

           /* Do important work that requires that the object
           be accessed by only one thread */
           obj.someImportantMethod();
       }
   }
}
Ето Howво се случва "под капака", след като компилаторът преобразува този code:

public class Main {

   private Object obj = new Object();

   public void doSomething() throws InterruptedException {

       // ...some logic, available for all threads

       // Logic available to just one thread at a time:
     
       /* as long as the object's mutex is busy,
       all the other threads (except the one that acquired it) are put to sleep */
       while (obj.getMutex().isBusy()) {
           Thread.sleep(1);
       }

       // Mark the object's mutex as busy
       obj.getMutex().isBusy() = true;

       /* Do important work that requires that the object
       be accessed by only one thread */
       obj.someImportantMethod();

       // Free the object's mutex
       obj.getMutex().isBusy() = false;
   }
}
Разбира се, това не е реален пример. Тук използвахме code, подобен на Java, за да изобразим Howво се случва вътре в Java машината. Въпреки това този псевдоcode дава отлично разбиране за това Howво всъщност се случва с обекта и нишките вътре в синхронизирания блок и How компилаторът преобразува тази ключова дума в няколко израза, които са „невидими“ за програмиста. По принцип Java използва ключовата дума synchronized за представяне на монитор . Целият code, който се появява instead of ключовата дума synchronized в последния пример, е мониторът.

Семафор

Друга дума, която ще срещнете в личното си изучаване на многонишковостта, е "семафор". Нека да разберем Howво е това и How се различава от монитор и мютекс. Семафорът е инструмент за синхронизиране на достъпа до няHowъв ресурс. Неговата отличителна черта е, че използва брояч за създаване на механизма за синхронизация. Броячът ни казва колко нишки могат едновременно да имат достъп до споделения ресурс. Каква е разликата между мютекс, монитор и семафор?  - 3Семафорите в Java са представени от класа Semaphore . Когато създаваме семафорни обекти, можем да използваме следните конструктори:

Semaphore(int permits)
Semaphore(int permits, boolean fair)
Предаваме следното на конструктора:
    int permits — началната и максималната стойност на брояча. С други думи, този параметър определя колко нишки могат едновременно да имат достъп до споделения ресурс;
  • boolean fair — установява реда, в който нишките ще получат достъп. Ако fair е true, тогава достъпът се предоставя на чакащите нишки в реда, в който са го поискали. Ако е невярно, тогава редът се определя от планировчика на нишки.
Класически пример за използване на семафор е проблемът с философа за хранене. Каква е разликата между мютекс, монитор и семафор?  - 4За да улесним разбирането, ще го опростим малко. Представете си, че имаме 5 философа, които трябва да обядват. Освен това имаме една маса, на която могат да се настанят едновременно не повече от двама души. Нашата задача е да нахраним всички философи. Никой от тях не трябва да остава гладен и никой от тях не трябва да се "блокира" един друг, когато се опитва да седне на масата (трябва да избягваме безизходицата). Ето How ще изглежда нашият клас по философия:

class Philosopher extends Thread {

   private Semaphore sem;

   // Did the philosopher eat?
   private boolean full = false;

   private String name;

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

   public void run()
   {
       try
       {
           // If the philosopher has not eaten
           if (!full) {
               // Ask the semaphore for permission to run
               sem.acquire();
               System.out.println(name + " takes a seat at the table");

               // The philosopher eats
               sleep(300);
               full = true;

               System.out.println(name + " has eaten! He leaves the table");
               sem.release();

               // The philosopher leaves, making room for others
               sleep(300);
           }
       }
       catch(InterruptedException e) {
           System.out.println("Something went wrong!");
       }
   }
}
И ето codeа за изпълнение на нашата програма:

public class Main {

   public static void main(String[] args) {

       Semaphore sem = new Semaphore(2);
       new Philosopher(sem, "Socrates").start();
       new Philosopher(sem,"Plato").start();
       new Philosopher(sem,"Aristotle").start();
       new Philosopher(sem, "Thales").start();
       new Philosopher(sem, "Pythagoras").start();
   }
}
Създадохме семафор, чийто брояч е настроен на 2, за да изпълни conditionто: само двама философи могат да ядат едновременно. Тоест, само две нишки могат да се изпълняват едновременно, защото нашият клас Philosopher наследява Thread ! Методите accept () и release() на класа Semaphore контролират неговия брояч за достъп. Методът accept() пита семафора за достъп до ресурса. Ако броячът е >0, тогава се предоставя достъп и броячът се намалява с 1. Release ()метод "освобождава" предоставения по-рано достъп, връщайки го към брояча (увеличава брояча за достъп на семафора с 1). Какво получаваме, когато стартираме програмата? Решен ли е проблемът? Дали нашите философи няма да се бият, докато чакат своя ред? :) Ето изхода от конзолата, който получихме:

Socrates takes a seat at the table 
Plato takes a seat at the table 
Socrates has eaten! He leaves the table 
Plato has eaten! He leaves the table 
Aristotle takes a seat at the table 
Pythagoras takes a seat at the table 
Aristotle has eaten! He leaves the table 
Pythagoras has eaten! He leaves the table 
Thales takes a seat at the table 
Thales has eaten! He leaves the table 
Успяхме! И въпреки че Талес трябваше да вечеря сам, не мисля, че сме го обидor :) Може би сте забелязали някои прorки между мутекс и семафор. Всъщност те имат една и съща мисия: да синхронизират достъпа до няHowъв ресурс. Каква е разликата между мютекс, монитор и семафор?  - 5Единствената разлика е, че мутексът на даден обект може да бъде придобит само от една нишка в даден момент, докато в случая на семафор, който използва брояч на нишки, няколко нишки могат да имат достъп до ресурса едновременно. Това не е просто съвпадение :) Мутексът всъщност е семафорс брой 1. С други думи, това е семафор, който може да поеме една нишка. Известен е още като „двоичен семафор“, защото броячът му може да има само 2 стойности — 1 („отключено“) и 0 („заключено“). Това е! Както можете да видите, в крайна сметка не е толкова объркващо :) Сега, ако искате да изучавате многонишковостта по-подробно в Интернет, ще ви бъде малко по-лесно да се ориентирате в тези концепции. Ще се видим в следващите уроци!
Коментари
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION