뮤텍스 란 무엇입니까?


653

뮤텍스는 멀티 스레딩 문제를 해결하는 데 자주 사용되는 프로그래밍 개념입니다. 커뮤니티에 대한 나의 질문 :

뮤텍스 란 무엇이며 어떻게 사용합니까?


2
차이점에 대한 좋은 기사가 여기 있습니다 : barrgroup.com/Embedded-Systems/How-To/RTOS-Mutex-Semaphore
Adam Davis

mutex에 대한 자습서는 문제를 해결하는 데 도움이 될 수 있습니다. stackoverflow.com/questions/4989451/mutex-example-tutorial
Nav

1
뮤텍스는 주유소의 화장실 열쇠와 같습니다. 한 번에 한 사람 만 화장실을 사용할 수 있으며 현재 탑승자가 끝나고 열쇠가 돌아올 때까지 아무도 화장실을 사용할 수 없습니다.
jonschlinkert

답변:


2152

직장에서 열띤 토론을 할 때 고무 닭을 사용하여 책상에 보관합니다. 닭을 안고있는 사람은 대화 할 수있는 유일한 사람입니다. 닭고기를 안들면 말할 수 없습니다. 닭고기를 원한다고 말하고 말하기 전에 닭고기를 먹을 때까지 기다리십시오. 말을 마치면 닭을 중재자에게 돌려주고 다음 사람에게 말을 건네줍니다. 이렇게하면 사람들이 서로 대화하지 않고 대화 할 공간이 생깁니다.

Chicken을 Mutex로 바꾸고 사람을 스레드로 바꾸면 기본적으로 mutex라는 개념이 있습니다.

물론 고무 뮤텍스와 같은 것은 없습니다. 고무 치킨 만. 내 고양이는 한때 고무 마우스를 먹었지 만 그것을 먹었습니다.

물론 고무 치킨을 사용하기 전에 실제로 한 방에 5 명이 필요한지 스스로에게 물어봐야하며 방에있는 한 사람이 혼자서 모든 일을하는 것이 더 쉬울 수는 없습니다. 실제로 이것은 유추를 확장 한 것이지만 아이디어를 얻습니다.


9
좋은 대답입니다. 뮤텍스가 실제로 닭고기 통과를 막는 규칙이라고 주장 할 수 있습니까? 닭은 당신이 잠그는 것입니까?
SirYakalot

3
@SirYakalot, 닭은 자원이고 중재자는 뮤텍스입니까?
Owen

156
닭은 뮤텍스 입니다. 뮤를 hoilding 사람들은 .. 닭되는 스레드를 경쟁 . 중재자는 OS 입니다. 사람들이 치킨을 요청하면 잠금 요청을합니다. mutex.lock ()을 호출하면 스레드가 lock ()에서 멈추고 OS에 잠금 요청을합니다. OS가 뮤텍스가 스레드에서 해제되었음을 감지하면 단순히 뮤텍스를 제공하고 lock ()이 반환합니다. 뮤텍스는 이제 귀하뿐입니다. lock ()을 호출하면 그를 막을 수 있기 때문에 아무도 그것을 훔칠 수 없습니다. 또한 뮤텍스가 귀하의 것이면 true를 차단하고 뮤텍스가 사용 중이면 즉시 false를 반환하는 try_lock ()도 있습니다.
Петър Петров

4
당신은 천재입니다. 고무 치킨 은유를 사용하여 모니터를 설명 할 수 있습니까?
Riccardo

98
때로는 일부 프로그래밍 개념의 기원이 불분명합니다. 초보자는 왜 모든 사람이 정규식에 대해 이야기하는지 궁금해 할 것입니다. 정규 표현식이 정규 표현식의 약어 인 것은 분명하지 않습니다. 유사하게, 뮤텍스는 상호 배제를 위해 짧다. 이것은 용어의 의미를 소화하기 쉽게 만들 수 있습니다. @TheSmurf는 답변에 링크했지만 역사적인 목적으로 여기에 추가하는 것이 좋습니다.
Dodzi Dzakuma

137

뮤텍스는 상호 배타적 인 플래그입니다. 하나의 스레드를 허용하고 다른 스레드에 대한 액세스를 차단하는 코드 섹션의 게이트 키퍼 역할을합니다. 이렇게하면 제어되는 코드가 한 번에 하나의 스레드 만 맞을 수 있습니다. 완료되면 뮤텍스를 해제하십시오. :)


10
뮤텍스는 코드 섹션 자체와 아무 관련이 없으며 일부 리소스를 보호 합니다. 뮤텍스가 해당 코드 주위에서만 사용되는 경우 해당 리소스는 코드 세그먼트 일 수 있지만 코드의 여러 위치에서 뮤텍스를 사용하기 시작하면 설명이 실패합니다. 일반적으로 코드의 여러 위치에서 액세스 할 수있는 일부 데이터 구조를 보호하는데도 사용할 수 있습니다.
paxdiablo

72

상호 배제. 여기에 Wikipedia 항목이 있습니다.

http://en.wikipedia.org/wiki/Mutual_exclusion

뮤텍스의 요점은 두 개의 스레드를 동기화하는 것입니다. 단일 리소스에 액세스하려는 두 개의 스레드가있는 경우 일반적인 패턴은 코드를 입력하기 전에 첫 번째 코드 블록이 뮤텍스를 설정하기 위해 액세스를 시도하는 것입니다. 두 번째 코드 블록이 액세스를 시도하면 뮤텍스가 설정된 것을 확인하고 첫 번째 코드 블록이 완료 될 때까지 기다렸다가 뮤텍스를 설정 해제합니다.

이것이 어떻게 달성되는지에 대한 구체적인 내용은 프로그래밍 언어에 따라 크게 다릅니다.


65

다중 스레드 응용 프로그램을 사용하는 경우 다른 스레드가 변수 또는 이와 같은 공통 리소스를 공유하는 경우가 있습니다. 이 공유 소스는 종종 동시에 액세스 할 수 없으므로 한 번에 하나의 스레드 만 해당 자원을 사용하도록하는 구성이 필요합니다.

이 개념을 "상호 배제"(짧은 뮤텍스)라고하며, 해당 리소스 등을 사용하여 해당 영역 내에 하나의 스레드 만 허용되도록하는 방법입니다.

그것들을 사용하는 방법은 언어마다 다르지만 종종 운영 체제 뮤텍스를 기반으로합니다 (항상 그렇지는 않지만).

기능 프로그래밍과 같은 패러다임으로 인해 일부 언어에는이 구문이 필요하지 않습니다 (Haskell, ML이 좋은 예입니다).


26

C #에서 사용되는 공통 뮤텍스는 Monitor 입니다. 유형은 ' System.Threading.Monitor '입니다. ' lock (Object) '문을 통해 암시 적으로 사용될 수도 있습니다 . 사용의 한 예는 Singleton 클래스를 생성 할 때입니다.

private static readonly Object instanceLock = new Object();
private static MySingleton instance;
public static MySingleton Instance
{
    lock(instanceLock)
    {
        if(instance == null)
        {
            instance = new MySingleton();
        }
        return instance;
    }
}

개인 잠금 오브젝트를 사용하는 잠금 문은 중요한 섹션을 작성합니다. 각 스레드가 이전 스레드가 완료 될 때까지 대기하도록 요구합니다. 첫 번째 스레드는 섹션으로 들어가 인스턴스를 초기화합니다. 두 번째 스레드는 대기하고 섹션으로 이동하여 초기화 된 인스턴스를 가져옵니다.

정적 멤버의 모든 종류의 동기화는 lock 문을 유사하게 사용할 수 있습니다.


1
이것은 구현에 따른 답변입니다. 또한 CS에서 모니터는 뮤텍스와 다릅니다. 모니터에는 동기화 메커니즘이 있지만 뮤텍스는 더 이상 필요하지 않을 때까지 물건을 잠급니다. 구현 세부 사항 또는 C #을 의미에 대해 IDK,하지만 난 질문의 맥락이 넓은 생각
marcoslhc

24

무엇 뮤텍스는 ?

스핀 록 (spinlock)이라고도하는 뮤텍스 (사실 뮤텍스라는 용어는 중요한 부분을 보호하고 경쟁 조건을 방지하는 데 사용되는 가장 간단한 동기화 도구)입니다. 즉, 스레드는 임계 섹션에 들어가기 전에 잠금을 획득해야합니다 (중요 섹션에서 다중 스레드는 공통 변수를 공유하고, 테이블을 업데이트하고 파일을 작성하는 등) 임계 섹션을 떠날 때 잠금을 해제합니다.

경쟁 조건 이란 무엇입니까 ?

경쟁 조건은 둘 이상의 스레드가 공유 데이터에 액세스 할 수 있고 동시에 변경하려고 할 때 발생합니다. 스레드 예약 알고리즘은 언제든지 스레드간에 교환 할 수 있으므로 스레드가 공유 데이터에 액세스하려는 순서를 모릅니다. 따라서, 데이터 변경의 결과는 스레드 스케줄링 알고리즘에 의존한다. 즉, 두 스레드 모두 데이터를 액세스 / 변경하기 위해 "경주"하고있다.

실제 예 :

직장에서 열띤 토론을 할 때, 나는 그런 경우를 위해 책상에 두는 고무 치킨을 사용합니다. 닭을 안고있는 사람은 대화 할 수있는 유일한 사람입니다. 닭고기를 안들면 말할 수 없습니다. 닭고기를 원한다는 말만하고 말하기 전에 닭이 나올 때까지 기다리십시오. 말을 마치면 닭고기를 다음 사람에게 건네주는 중재자에게 닭을 돌려 줄 수 있습니다. 이렇게하면 사람들이 서로 대화하지 않고 대화 할 공간이 생깁니다.

Chicken을 Mutex로 바꾸고 사람을 스레드로 바꾸면 기본적으로 mutex라는 개념이 있습니다.

X

C #에서의 사용법 :

이 예는 로컬 Mutex 객체를 사용하여 보호 된 리소스에 대한 액세스를 동기화하는 방법을 보여줍니다. 각 호출 스레드는 뮤텍스의 소유권을 얻을 때까지 차단되므로 스레드의 소유권을 해제하려면 ReleaseMutex 메소드를 호출해야합니다.

using System;
using System.Threading;

class Example
{
    // Create a new Mutex. The creating thread does not own the mutex.
    private static Mutex mut = new Mutex();
    private const int numIterations = 1;
    private const int numThreads = 3;

    static void Main()
    {
        // Create the threads that will use the protected resource.
        for(int i = 0; i < numThreads; i++)
        {
            Thread newThread = new Thread(new ThreadStart(ThreadProc));
            newThread.Name = String.Format("Thread{0}", i + 1);
            newThread.Start();
        }

        // The main thread exits, but the application continues to
        // run until all foreground threads have exited.
    }

    private static void ThreadProc()
    {
        for(int i = 0; i < numIterations; i++)
        {
            UseResource();
        }
    }

    // This method represents a resource that must be synchronized
    // so that only one thread at a time can enter.
    private static void UseResource()
    {
        // Wait until it is safe to enter.
        Console.WriteLine("{0} is requesting the mutex", 
                          Thread.CurrentThread.Name);
        mut.WaitOne();

        Console.WriteLine("{0} has entered the protected area", 
                          Thread.CurrentThread.Name);

        // Place code to access non-reentrant resources here.

        // Simulate some work.
        Thread.Sleep(500);

        Console.WriteLine("{0} is leaving the protected area", 
            Thread.CurrentThread.Name);

        // Release the Mutex.
        mut.ReleaseMutex();
        Console.WriteLine("{0} has released the mutex", 
            Thread.CurrentThread.Name);
    }
}
// The example displays output like the following:
//       Thread1 is requesting the mutex
//       Thread2 is requesting the mutex
//       Thread1 has entered the protected area
//       Thread3 is requesting the mutex
//       Thread1 is leaving the protected area
//       Thread1 has released the mutex
//       Thread3 has entered the protected area
//       Thread3 is leaving the protected area
//       Thread3 has released the mutex
//       Thread2 has entered the protected area
//       Thread2 is leaving the protected area
//       Thread2 has released the mutex

MSDN 참조 뮤텍스


1
아주 좋은 예
Siwei Shen 申思维

22

여기에 훌륭한 답변이 있습니다. 여기에 뮤텍스 가 무엇인지 설명하는 또 다른 훌륭한 비유 가 있습니다.

열쇠 가있는 싱글 화장실을 고려하십시오 . 누군가가 들어 오면 열쇠를 가져 가고 화장실이 차지 합니다. 다른 사람이 화장실을 사용해야하는 경우 대기열 에서 기다려야합니다 . 화장실에있는 사람이 끝나면 키를 대기열에있는 다음 사람에게 전달합니다. 이해가 되나요?

변환 화장실을 A와 스토리에 공유 자원 , 그리고 A와 뮤텍스 . 화장실 열쇠를 가져 가면 (자물쇠 획득) 사용할 수 있습니다. 키가없는 경우 (잠금이 잠김) 기다려야합니다. 사람이 열쇠를 반환하면 ( 자물쇠를 놓음 ) 이제 열쇠 를 얻을 수 있습니다.


그러나 C # 예제는 "큐의 다음 사람에게 키를 전달합니다"라는 큐 어설 션을 지원하지 않습니다. 이 예제는 스택 또는 랜덤을 시연합니다. 1, 2 및 3은 모두 해당 순서로 액세스를 요청합니다. 하나는 먼저 보호 구역으로 들어간 다음 3 개가 허용됩니다. 대기열이 두 번째 대기열에 제공했을 것입니다.
donvnielsen

구체적인 구현이나 구체적인 프로그래밍 언어를 언급하지 않았습니다. 나의 예는 원칙적으로 뮤텍스의 고수준 추상화와 관련이 있습니다.
Chen A.

18

처음에 MUTEX를 이해하려면 "경주 조건"이 무엇인지 알아야하며 MUTEX이 필요한 이유 만 이해하게됩니다. 다중 스레딩 프로그램이 있고 두 개의 스레드가 있다고 가정하십시오. 이제 작업 대기열에 하나의 작업이 있습니다. 첫 번째 스레드는 작업 큐를 확인하고 작업을 찾은 후 실행을 시작합니다. 두 번째 스레드는 작업 대기열을 확인하고 대기열에 작업이 하나 있음을 발견합니다. 따라서 동일한 작업 포인터도 할당합니다. 이제 두 스레드가 동일한 작업을 실행하고 있습니다. 이로 인해 분할 오류가 발생합니다. 이것이 경쟁 조건의 예입니다.

이 문제에 대한 해결책은 MUTEX입니다. MUTEX는 한 번에 하나의 스레드를 잠그는 일종의 잠금 장치입니다. 다른 스레드가이를 잠 그려면 스레드가 단순히 차단됩니다.

이 pdf 파일 링크 의 MUTEX 주제 는 실제로 읽을 가치가 있습니다.


"MUTEX topic"은 세마포어에 대한 섹션을 의미합니다. 예제는 이진 세마포어이기 때문입니다.
Carl G

2
음 뮤텍스는 값이 1 인 세마포
일뿐입니다.

공유 한 장의 책 이름은 무엇입니까? 제발
Omar Faroque Anik

@OmarFaroqueAnik이 참조한이 책은 New Riders Publishing에서 발행 한 CodeSourcery LLC의 Advanced Linux Programming이며 링크 된 도메인의 홈 페이지에서 액세스 할 수 있습니다.
RMart

11

뮤텍스는 여러 프로세스에 걸쳐 리소스에 독점적으로 액세스해야하는 상황에서 유용하며, 스레드 전체에서만 작동하므로 일반 잠금이 도움이되지 않습니다.


정말 맞습니까? 개별 프로세스가 자체 뮤텍스 복사본을 생성하지 않습니까?
레온

0

Mutex : Mutex는 Mut ual Ex를 나타냅니다 clusion. 한 번에 하나의 프로세스 / 스레드가 중요한 섹션으로 들어갈 수 있음을 의미합니다. 여러 스레드 / 프로세스가 공유 리소스 (변수, 공유 메모리 등)를 업데이트하려고하는 동시 프로그래밍에서 예기치 않은 결과가 발생할 수 있습니다. (결과는 어느 스레드 / 프로세스가 첫 번째 액세스 권한을 갖는지에 따라 다릅니다).

이러한 예기치 않은 결과를 피하기 위해서는 한 번에 하나의 스레드 / 프로세스 만 해당 리소스에 액세스 할 수 있도록 동기화 메커니즘이 필요합니다.

pthread 라이브러리는 Mutex를 지원합니다.

typedef union
{
  struct __pthread_mutex_s
  {
    ***int __lock;***
    unsigned int __count;
    int __owner;
#ifdef __x86_64__
    unsigned int __nusers;
#endif
 int __kind;
#ifdef __x86_64__
    short __spins;
    short __elision;
    __pthread_list_t __list;
# define __PTHREAD_MUTEX_HAVE_PREV      1
# define __PTHREAD_SPINS             0, 0
#else
    unsigned int __nusers;
    __extension__ union
    {
      struct
      {
        short __espins;
        short __elision;
# define __spins __elision_data.__espins
# define __elision __elision_data.__elision
# define __PTHREAD_SPINS         { 0, 0 }
      } __elision_data;
      __pthread_slist_t __list;
    };
#endif

이것은 뮤텍스 데이터 형식, 즉 pthread_mutex_t의 구조입니다. 뮤텍스가 잠기면 __lock은 1로 설정되고, 잠금이 해제되면 __lock은 0으로 설정됩니다.

이렇게하면 두 프로세스 / 스레드가 동시에 중요한 섹션에 액세스 할 수 없습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.