2017-09-22 3 views
1

자물쇠가없는 진보 보장을 충족하는 쓰기 알고리즘 또는 데이터 구조의 어려움 중 하나는 동적 메모리 할당입니다. malloc 또는 new과 같은 호출은 휴대용 방식으로 잠금이 해제되지 않을 수 있습니다 . 그러나 많은 잠금이 필요없는 구현 인 malloc 또는 new이 있으며 잠금없는 알고리즘/데이터 구조를 구현하는 데 사용할 수있는 다양한 잠금없는 메모리 할당자가 있습니다.동적 잠금없는 메모리 할당 자

그러나 데이터 구조 나 알고리즘을 미리 할당 된 정적 메모리 풀로 특별히 제한하지 않는 한 실제로 이것이 잠금없는 진행 보장을 어떻게 완전히 만족시킬 수 있는지는 여전히 이해할 수 없습니다. 하지만 동적 인 메모리 할당이 필요하다면, 장기간에 걸쳐 lock-free 메모리 할당자가 맹목적으로 잠금을 해제 할 수있는 방법을 이해하지 못합니다. 문제는 잠금 장치가없는 malloc 또는 new이 얼마나 놀랍지 만 궁극적으로 메모리가 부족하여 운영 체제에 더 많은 메모리를 요청해야 할 때가 있습니다. 즉 궁극적으로 더 많은 메모리에 실제로 액세스하려면 brk() 또는 mmap() 또는 이와 같은 하위 수준 코드를 호출해야합니다. 그리고 이러한 낮은 수준의 호출이 잠금없는 방식으로 구현된다는 보장은 없습니다.

메모리 보호를 제공하지 않는 MS-DOS와 같은 고대 OS를 사용하거나 완전히 자물쇠가없는 운영 체제를 작성하지 않는 한이 방법을 사용하면 안됩니다. 실용적이지 않은 두 가지 시나리오 그렇다면 어떻게 동적 메모리 할당자가 정말로 lock-free가 될 수 있습니까?

+1

맞아요 ...하지만 할당 자만 OS에서 큰 블록 만 요청하기 때문에 'sbrk()'에 대한 총 호출 횟수 또는 문제가되지 않는 지점까지 엄격하게 제한 할 수있는 모든 항목을 적시에 릴리스 할 필요는 없습니다. 물론 이것은 까다로운 실시간 요구 사항을 만족 시키지는 못하지만 동적 할당이 완전히 자물쇠가 없더라도 그러한 요구 사항을 만족시킬 것이라고는 생각하지 않습니다. –

+0

지연에 대해 걱정 하시거나 https://en.wikipedia.org/wiki/Nonblocking_algorithm을 사용 하시겠습니까? 후자의 경우, 가장 좋은 OS는 다른 스레드가 mmap을 사용하지 못하도록 잠금을 유지하면서 스레드가 커널 내부에서 잠자기하는 것이 불가능하다고 생각합니다. 그래서 nonblocking 알고리즘을 작성하는 한, 스레드를 잠자 게하는 것이 가능하다면 잠금은 문제가되기 때문에 기술적으로는'mmap'을 사용하는 것이 문제가 아니라고 생각합니다. 크리티컬 섹션 내부의 몇 가지 CPU 캐시 미스는 아마도 당신이 얻는 최악의 경우 일 것이다. –

+0

실제 시스템에서 실행되는 모든 할당자는 어느 시점에서 메모리를 모두 사용해야합니다. 고정 풀이 할당 될 때 잠금 해제 할당 자 (lock-free allocator)가 부족하다는 것은 운영체제가 충분하다고 판단 할 때 정상적인 할당 자와 질적으로 다른 점이다. –

답변

3

근본적인 OS 할당자는 잠금이 필요하지 않을 것입니다. 다중 프로세스와 모든 종류의 흥미로운 것들을 처리해야하기 때문에 일종의 잠금을 도입하지 않는 것이 정말 어렵습니다.

그러나 "잠금 해제 메모리 할당"은 "잠금을 해제하지 않음"이 아니라 "통계적으로 너무 중요하지 않으므로 통계적으로 잠김"을 의미하지 않습니다. 가장 엄격한 실시간 시스템 이외에는 괜찮습니다. 자물쇠에 높은 논쟁이 없다면 자물쇠 또는 아무 잠금도 중요하지 않습니다. 자물쇠가없는 목적은 자물쇠 자체의 오버 헤드가 아니라 병목이되는 용이성입니다 시스템의 모든 쓰레드 나 프로세스가이 한 장소를 통과하여 유용한 것을 수행해야하며, 대기열에서 기다려야한다. [실제 큐가 아닐 수도 있지만, "누구든지 먼저 깨우는" 또는 현재 발신자 다음에 누가 다음에 나올지를 결정하는 다른 메커니즘]. 당신은 유한 한 크기의 메모리 풀이있는 경우 소프트웨어가 시작되는 때

  • , 당신은, 한 번에 모든 메모리의 OS를 요청할 수 있습니다 :

    는이 문제를 해결하기 위해 몇 가지 옵션이 있습니다 . 그리고 메모리가 OS에서 덩어리로 만들어지면 잠금없는 풀로 사용할 수 있습니다. 분명한 단점은 할당 할 수있는 메모리 양에 제한이 있다는 것입니다. 그런 다음 할당을 중지해야합니다 (응용 프로그램을 모두 실패하거나 특정 작업을 실패합니다).

    물론 Linux 나 Windows와 같은 시스템에서 시스템은 lock-free 시나리오에서 "할당 된 메모리에 즉시 액세스"한다는 것을 보장하지 않습니다. 시스템이 메모리를 할당 할 수 있기 때문에 실제 메모리가 실제로 사용 중이면 실제 메모리 페이지가 할당됩니다. 이것은 스왑에 다른 페이지를 페이지 아웃하기 위해 잠금과 예를 들어 디스크 -I/O를 포함 할 수 있습니다.

  • 잠금 장치를 놓고 경쟁 할 수있는 단일 시스템 호출 시간이 "너무 많음"과 같은 엄격한 실시간 시스템의 경우 솔루션은 물론 잠금이 해제 된 전용 OS를 사용해야합니다 할당 자 (또는 허용 가능한 실시간 동작이 적어도 하나 이상 - X 초 이하일 수 있음 (X는 1.0보다 작을 수 있음)). 실시간 시스템은 종종 오래된 할당을 재활용하기 위해 메모리 풀과 고정 크기 버킷을 가지고 있습니다. 잠금없이 사용할 수 있습니다 - 버킷은 링크 된 목록이므로 원자 적 비교로 삽입/제거 할 수 있습니다 & [다시 시도 할 수 있으므로 기술적으로 잠금 장치가 없어도 경쟁 상황에서는 대기 시간이 0이되지 않습니다.]

  • "스레드 당 풀"을 사용할 수있는 또 다른 솔루션이 있습니다. 이것은 스레드간에 데이터를 전달할 때 조금 복잡해 질 수 있습니다. 그러나 "재사용을 위해 해제 된 메모리가 다른 스레드에서 종료 될 수 있습니다"(물론 "모든 메모리가 현재 위치합니다"라는 라인을 따라 문제가 발생합니다 다른 많은 스레드에서 정보를 수집하고 해제하는 하나의 스레드, 다른 모든 스레드는 메모리가 부족합니다 ")