뮤텍스가 다른 문제를 해결하는 데 사용될 수 있지만 이들이 존재하는 주된 이유는 상호 배제를 제공하여 경쟁 조건으로 알려진 것을 해결하는 것입니다. 두 개 이상의 스레드 또는 프로세스가 동일한 변수에 동시에 액세스하려고하면 경쟁 조건이 발생할 수 있습니다. 다음 코드를 고려하십시오
//somewhere long ago, we have i declared as int
void my_concurrently_called_function()
{
i++;
}
이 함수의 내부는 매우 단순 해 보입니다. 하나의 진술 일뿐입니다. 그러나 일반적인 의사 어셈블리 언어는 다음과 같습니다.
load i from memory into a register
add 1 to i
store i back into memory
i에서 증분 작업을 수행하려면 동등한 어셈블리 언어 명령어가 모두 필요하므로 i를 증분하는 것은 비대기 작업이라고합니다. 원 자성 작업은 명령 실행이 시작된 후에 중단되지 않는 보증으로 하드웨어에서 완료 될 수있는 작업입니다. i를 증가 시키면 3 개의 원자 명령어 체인으로 구성됩니다. 여러 스레드가 함수를 호출하는 동시 시스템에서 스레드가 잘못된 시간에 읽거나 쓸 때 문제가 발생합니다. 동시 실행을 실행하는 두 개의 스레드가 있고 하나는 즉시 다른 함수를 호출한다고 상상해보십시오. 또한 0으로 초기화했다고 가정 해 봅시다. 또한 레지스터가 많고 두 스레드가 완전히 다른 레지스터를 사용한다고 가정하므로 충돌이 발생하지 않습니다. 이러한 이벤트의 실제 타이밍은 다음과 같습니다.
thread 1 load 0 into register from memory corresponding to i //register is currently 0
thread 1 add 1 to a register //register is now 1, but not memory is 0
thread 2 load 0 into register from memory corresponding to i
thread 2 add 1 to a register //register is now 1, but not memory is 0
thread 1 write register to memory //memory is now 1
thread 2 write register to memory //memory is now 1
일어난 일은 동시에 두 개의 스레드가 증가하고 함수가 두 번 호출되지만 결과는 그 사실과 일치하지 않습니다. 함수가 한 번만 호출 된 것 같습니다. 이는 기계 수준에서 원 자성이 "파손"되었기 때문에 스레드가 서로 방해하거나 잘못된 시간에 함께 작동 할 수 있습니다.
이를 해결하기위한 메커니즘이 필요합니다. 위의 지침에 따라 주문을해야합니다. 하나의 일반적인 메커니즘은 하나를 제외한 모든 스레드를 차단하는 것입니다. Pthread mutex는이 메커니즘을 사용합니다.
전화로 아내와 대화하기 위해 다른 스레드가 공유 값을 안전하지 않게 수정할 수있는 일부 코드 행을 실행해야하는 스레드는 먼저 뮤텍스에 대한 잠금을 획득해야합니다. 이러한 방식으로 공유 데이터에 액세스해야하는 모든 스레드는 뮤텍스 잠금을 통과해야합니다. 그래야만 스레드가 코드를 실행할 수 있습니다. 이 코드 섹션을 중요 섹션이라고합니다.
스레드가 중요한 섹션을 실행하면 다른 스레드가 뮤텍스에 대한 잠금을 획득 할 수 있도록 뮤텍스에 대한 잠금을 해제해야합니다.
실제 물리적 객체에 독점적으로 액세스하려는 인간을 고려할 때 뮤텍스를 갖는 개념은 약간 이상하게 보이지만 프로그래밍 할 때는 의도적이어야합니다. 동시 스레드와 프로세스는 우리가하는 사회적, 문화적 양육이 없으므로 데이터를 잘 공유하도록 강요해야합니다.
기술적으로 말하자면 뮤텍스는 어떻게 작동합니까? 앞에서 언급 한 것과 동일한 경쟁 조건으로 고통받지 않습니까? pthread_mutex_lock ()은 변수의 단순한 증분보다 조금 더 복잡하지 않습니까?
기술적으로 말하면, 우리를 돕기 위해 약간의 하드웨어 지원이 필요합니다. 하드웨어 설계자들은 하나 이상의 작업을 수행하지만 원 자성이 보장되는 기계 명령어를 제공합니다. 이러한 명령어의 전형적인 예는 TAS (Test-and-Set)입니다. 리소스에 대한 잠금을 얻으려고 할 때 TAS는 메모리의 값이 0인지 확인하기 위해 사용할 수 있습니다. 만약 그렇다면, 리소스가 사용 중이고 아무것도하지 않는다는 신호일 것입니다. pthreads mutex는 우리를 운영 체제의 특수 대기열에 넣고 리소스를 사용할 수있게되면 알려줄 것입니다. . 메모리의 값이 0이 아닌 경우 TAS는 다른 명령을 사용하지 않고 위치를 0 이외의 다른 위치로 설정합니다. 그것' 두 개의 조립 명령을 1로 결합하여 원 자성을 부여하는 것과 같습니다. 따라서 값이 변경되면 테스트 및 변경 (적절한 경우)을 중단 할 수 없습니다. 그러한 명령 위에 뮤텍스를 만들 수 있습니다.
참고 : 일부 섹션은 이전 답변과 유사하게 나타날 수 있습니다. 나는 편집에 대한 그의 초대를 받아 들였고, 원래의 방식을 선호했기 때문에 내가 가진 것을 조금 그의 언어로 주입하고 있습니다.