JavaRush /Java Blog /Random-KO /뮤텍스, 모니터 및 세마포어의 차이점은 무엇입니까

뮤텍스, 모니터 및 세마포어의 차이점은 무엇입니까

Random-KO 그룹에 게시되었습니다
안녕하세요! JavaRush에서 멀티스레딩을 공부하면서 "뮤텍스"와 "모니터"라는 개념을 자주 접하게 되었습니다. 이제 엿보지 않고 그들이 어떻게 다른지 답할 수 있습니까? :) 뮤텍스, 모니터 및 세마포어의 차이점은 무엇입니까 - 1가능하다면 잘 하셨습니다! 그렇지 않은 경우(대개 이런 일이 발생함) - 당연한 일입니다. "뮤텍스"와 "모니터"의 개념은 실제로 서로 관련되어 있습니다. 또한 인터넷의 외부 리소스에서 멀티스레딩에 대한 강의를 읽고 비디오를 시청하는 동안 "세마포어"라는 또 다른 유사한 개념을 접하게 됩니다. 그 기능도 모니터 및 뮤텍스와 대체로 유사합니다. 그러므로 이 세 가지 용어를 이해하고 몇 가지 예를 살펴보고 마지막으로 서로 어떻게 다른지에 대한 이해를 머릿속으로 정리합시다 :)

뮤텍스

뮤텍스는 스레드 동기화를 위한 특수 개체입니다. 이는 Java의 모든 객체에 "부착"됩니다. 여러분은 이미 알고 있습니다 :) 표준 클래스를 사용하든 자신만의 클래스를 생성하든 상관없습니다. 예를 들어 모든 Cat클래스 의 모든 객체에는 뮤텍스가 있습니다 . "뮤텍스"라는 이름은 영어 "MUTual EXclusion"- "상호 배제"에서 유래되었으며 이는 그 목적을 완벽하게 반영합니다. 이전 강의 중 하나에서 말했듯 이 뮤텍스의 임무는 특정 시간에 하나의 스레드만 개체에 액세스할 수 있도록 이러한 메커니즘을 제공하는 것입니다 . 실제 생활에서 뮤텍스에 대한 인기 있는 비유는 "화장실 예"입니다. 사람이 화장실에 들어가면 안쪽에서 문을 잠급니다. 화장실은 여러 스레드에서 액세스할 수 있는 개체 역할을 합니다. 화장실 문의 자물쇠는 뮤텍스의 역할이고, 밖에 사람들이 줄지어 있는 줄은 스레드의 역할입니다. 문에 있는 자물쇠는 화장실 뮤텍스로, 한 번에 한 사람만 안에 들어갈 수 있도록 해줍니다. 즉, 한 번에 하나의 스레드만 공유 리소스에 대해 작업할 수 있습니다. 다른 스레드(사람)가 점유된 리소스에 액세스하려는 시도는 실패합니다. 뮤텍스에는 몇 가지 중요한 기능이 있습니다. 첫째 , "한가함"과 "바쁨"이라는 두 가지 상태만 가능합니다. 이렇게 하면 작동 방식을 더 쉽게 이해할 수 있습니다. 부울 변수 true/false 또는 이진수 시스템 1/0을 사용하여 평행선을 그릴 수 있습니다. 둘째 , 상태를 직접 제어할 수 없습니다. Java에는 명시적으로 객체를 가져와 해당 뮤텍스를 가져오고 원하는 상태를 객체에 할당할 수 있는 메커니즘이 없습니다. 즉, 다음과 같은 작업을 수행할 수 없습니다. Dog뮤텍스, 모니터 및 세마포어의 차이점은 무엇입니까 - 2
Object myObject = new Object();
Mutex mutex = myObject.getMutex();
mutex.free();
따라서 개체의 뮤텍스를 해제할 수 없습니다. Java 시스템만이 이에 직접 액세스할 수 있습니다. 프로그래머는 언어 도구를 사용하여 뮤텍스로 작업합니다.

감시 장치

모니터는 뮤텍스에 대한 추가 "추가 기능"입니다. 실제로 모니터는 프로그래머에게 "보이지 않는" 코드 조각입니다 . 앞서 뮤텍스에 대해 말하면서 간단한 예를 들었습니다.
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
       }
   }
}
단어로 표시된 코드 블록에서 synchronized개체의 뮤텍스가 캡처됩니다 obj. 좋아요, 포획이 이루어졌습니다. 그런데 "방어 메커니즘"은 정확히 어떻게 달성됩니까? 왜 다른 스레드는 단어를 볼 때 synchronized블록 안으로 들어갈 수 없나요 ? 보호 메커니즘을 만들어내는 것이 바로 모니터입니다! 컴파일러는 이 단어를 synchronized몇 가지 특별한 코드 조각으로 변환합니다. 다시 한 번 메소드를 사용하여 예제로 돌아가서 doSomething()여기에 추가해 보겠습니다.
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();
       }
   }
}
컴파일러가 이 코드를 변환한 후 프로그램의 "내부"에서는 다음과 같은 일이 발생합니다.
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;
   }
}
물론 그 예는 실제가 아니다. 여기서는 자바와 유사한 코드를 사용하여 지금 이 순간 자바 머신 내부에서 무슨 일이 일어나고 있는지 반영하려고 했습니다. 그러나 이 의사코드는 블록 내부의 객체와 스레드에서 실제로 무슨 일이 일어나고 있는지, synchronized그리고 컴파일러가 이 단어를 프로그래머에게 "보이지 않는" 여러 명령으로 변환하는 방법에 대한 훌륭한 이해를 제공합니다. 기본적으로 Java에서 모니터는 이라는 단어를 사용하여 표현됩니다synchronized . 마지막 예시에서 단어 대신 등장한 코드가 모두 synchronized모니터입니다.

신호기

멀티스레딩을 혼자 공부할 때 접하게 되는 또 다른 단어는 '세마포어'입니다. 이것이 무엇인지, 모니터 및 뮤텍스와 어떻게 다른지 알아봅시다. 세마포어는 리소스에 대한 액세스를 동기화하는 수단입니다. 그 특징은 동기화 메커니즘을 생성할 때 카운터를 사용한다는 것입니다. 카운터는 공유 리소스에 동시에 액세스할 수 있는 스레드 수를 알려줍니다. 뮤텍스, 모니터 및 세마포어의 차이점은 무엇입니까 - 3Java의 세마포어는 클래스로 표시됩니다 Semaphore. 세마포어 객체를 생성할 때 다음 생성자를 사용할 수 있습니다.
Semaphore(int permits)
Semaphore(int permits, boolean fair)
생성자에 전달합니다.
  • int permits— 초기 및 최대 카운터 값. 즉, 공유 리소스에 동시에 액세스할 수 있는 스레드 수입니다.

  • boolean fair- 스레드가 액세스를 받는 순서를 설정합니다. fair= true 인 경우 요청한 순서대로 대기 중인 스레드에 액세스 권한이 부여됩니다. false 이면 스레드 스케줄러에 의해 순서가 결정됩니다.

세마포어 사용의 전형적인 예는 점심을 먹는 철학자 문제 입니다 .
뮤텍스, 모니터 및 세마포어의 차이점은 무엇입니까 - 4
더 나은 이해를 위해 용어를 조금 단순화하겠습니다. 점심이 필요한 철학자 5명이 있다고 상상해 보세요. 동시에, 우리는 하나의 테이블을 가지고 있으며 동시에 두 명 이상이 테이블에 앉을 수 없습니다. 우리의 임무는 모든 철학자들에게 먹이를 주는 것입니다. 둘 다 배가 고프지 않아야 하고, 테이블에 앉으려고 할 때 서로를 '막아'서는 안 됩니다(교착 상태를 피해야 합니다). 이것이 우리 철학자 수업의 모습입니다:
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-то пошло не так!");
       }
   }
}
다음은 프로그램을 실행하는 코드입니다.
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();
   }
}
동시에 두 명의 철학자만 먹을 수 있다는 조건을 만족시키기 위해 개수가 2인 세마포어를 만들었습니다. 즉, 우리 클래스 가 ! Philosopher에서 상속되었기 때문에 두 개의 스레드만 동시에 작동할 수 있습니다. 클래스 와 Thread메서드는 해당 권한 카운터를 제어합니다. 이 메서드는 세마포어에서 리소스에 액세스할 수 있는 권한을 요청합니다. 카운터 > 0이면 권한이 부여되고 카운터는 1씩 감소합니다. 메서드는 이전에 부여된 권한을 "해제"하고 이를 카운터에 반환합니다(세마포어의 부여 카운터를 1씩 증가). 프로그램을 실행하면 무엇을 얻게 되나요? 문제는 해결됐는가, 우리 철학자들은 차례를 기다리며 싸울 것인가. :) 이것은 우리가 받은 콘솔 출력입니다. 소크라테스는 테이블에 앉습니다. 플라톤은 소크라테스가 먹은 테이블에 앉습니다! 그는 식탁을 떠났고 플라톤은 식사를 했습니다! 그는 식탁을 떠난다 아리스토텔레스는 식탁에 앉는다 피타고라스는 아리스토텔레스가 먹은 식탁에 앉는다! 그는 피타고라스가 먹은 식탁을 떠났습니다! 그는 식탁을 떠나고 탈레스는 탈레스가 먹은 식탁에 앉는다 ! 그는 테이블을 떠났습니다. 우리는 성공했습니다! 탈레스는 혼자 식사를 해야 했지만 우리에게 화를 내지는 않은 것 같아요 :) 뮤텍스와 세마포어 사이에 몇 가지 유사점을 발견했을 수도 있습니다. 일반적으로 일부 리소스에 대한 액세스를 동기화하는 동일한 목적을 가지고 있습니다. 유일한 차이점은 객체의 뮤텍스는 한 번에 하나의 스레드에서만 획득할 수 있는 반면, 세마포어의 경우 스레드 카운터가 사용되며 그 중 여러 개가 동시에 리소스에 액세스할 수 있다는 것입니다. 그리고 이것은 단지 우연의 유사성이 아닙니다 :) 실제로 뮤텍스는 단일 위치 세마포어입니다 . 즉, 카운터가 초기에 1로 설정된 세마포어입니다. 카운터가 1("free")과 0("busy")의 2가지 값만 가질 수 있기 때문에 "바이너리 세마포어"라고도 합니다. 그게 다야! 보시다시피 모든 것이 그다지 혼란스럽지 않은 것으로 나타났습니다. :) 이제 인터넷에서 멀티스레딩 주제를 더 자세히 연구하고 싶다면 개념을 탐색하는 것이 조금 더 쉬울 것입니다. 다음 강의에서 뵙겠습니다! acquire()release()Semaphoreacquire()release()뮤텍스, 모니터 및 세마포어의 차이점은 무엇입니까 - 5
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION