다중 스레드 아파트먼트
다중 스레드 아파트 모델에서는 자유 스레드로 초기화된 프로세스의 모든 스레드가 단일 아파트에 상주합니다. 따라서 스레드 간에 마샬링할 필요가 없습니다. COM은 이 모델에서 창 메시지를 사용하지 않으므로 스레드에서 메시지를 검색하고 디스패치할 필요가 없습니다.
다중 스레드 아파트의 개체 메서드에 대한 호출은 아파트의 모든 스레드에서 실행할 수 있습니다. 호출의 serialization은 없습니다. 동일한 메서드 또는 동일한 개체에 대해 동시에 많은 호출이 발생할 수 있습니다. 다중 스레드 아파트에서 만든 개체는 언제든지 다른 스레드에서 메서드에 대한 호출을 처리할 수 있어야 합니다.
개체에 대한 호출은 어떤 방식으로도 직렬화되지 않으므로 다중 스레드 개체 동시성은 가장 높은 성능을 제공하며 크로스 스레드, 크로스 프로세스 및 컴퓨터 간 호출을 위해 다중 프로세서 하드웨어를 가장 잘 활용합니다. 그러나 개체에 대한 코드는 일반적으로 이 섹션의 뒷부분에 설명된 이벤트 개체, 중요한 섹션, 뮤텍스 또는 세마포와 같은 동기화 기본 형식을 사용하여 인터페이스 구현에서 동기화를 제공해야 합니다. 또한 개체가 액세스하는 스레드의 수명을 제어하지 않으므로 스레드별 상태가 개체(스레드 로컬 스토리지)에 저장되지 않을 수 있습니다.
다음은 다중 스레드 아파트의 동기화와 관련된 몇 가지 중요한 고려 사항입니다.
- COM은 단일 스레드 아파트에 대해서만 통화 동기화를 제공합니다.
- 다중 스레드 아파트는 같은 스레드에서 전화를 걸 때 전화를 받지 않습니다.
- 다중 스레드 아파트는 입력 동기화된 호출을 수행할 수 없습니다.
- 비동기 호출은 다중 스레드 아파트의 동기 호출로 변환됩니다.
- 다중 스레드 아파트의 스레드에 대해 메시지 필터가 호출되지 않습니다.
스레드를 자유 스레드로 초기화하려면 CoInitializeEx를 호출하고 COINIT_MULTITHREADED 지정합니다. In-Process 서버 스레딩에 대한 자세한 내용은 In-Process 서버 스레딩 문제를 참조하세요.
여러 클라이언트는 서로 다른 스레드에서 자유 스레딩을 지원하는 개체를 동시에 호출할 수 있습니다. 자유 스레드 아웃 오브 프로세스 서버에서 COM은 RPC 하위 시스템을 통해 서버 프로세스에 스레드 풀을 만들고 클라이언트 호출(또는 여러 클라이언트 호출)을 언제든지 이러한 스레드에서 배달할 수 있습니다. 또한 out-of-process 서버는 클래스 팩터리에서 동기화를 구현해야 합니다. 자유 스레드의 in-process 개체는 클라이언트의 여러 스레드에서 직접 호출을 받을 수 있습니다.
클라이언트는 여러 스레드에서 COM 작업을 수행할 수 있습니다. 모든 스레드는 동일한 다중 스레드 아파트에 속합니다. 인터페이스 포인터는 다중 스레드 아파트 내에서 스레드에서 스레드로 직접 전달되므로 인터페이스 포인터는 스레드 간에 마샬링되지 않습니다. 메시지 필터( IMessageFilter 구현)는 다중 스레드 아파트에서 사용되지 않습니다. 클라이언트 스레드는 아파트 외부 개체에 대한 COM 호출을 수행할 때 일시 중단되고 호출이 반환될 때 다시 시작됩니다. 프로세스 간의 호출은 RPC에서 여전히 처리됩니다.
자유 스레드 모델로 초기화된 스레드는 자체 동기화를 구현해야 합니다. 이 섹션의 앞부분에서 설명한 것처럼 Windows는 다음 동기화 기본 형식을 통해 이 구현을 사용하도록 설정합니다.
- 이벤트 개체는 이벤트가 발생했음을 하나 이상의 스레드에 알리는 방법을 제공합니다. 프로세스 내의 모든 스레드는 이벤트 개체를 만들 수 있습니다. 이벤트에 대한 핸들은 이벤트 만들기 함수인 CreateEvent에서 반환됩니다. 이벤트 개체가 만들어지면 개체에 대한 핸들이 있는 스레드가 계속 실행되기 전에 대기할 수 있습니다.
- 중요한 섹션은 실행되기 전에 일부 공유 데이터 집합에 대한 단독 액세스가 필요하고 단일 프로세스 내의 스레드에서만 사용되는 코드 섹션에 사용됩니다. 중요한 섹션은 다음과 같이 한 번에 하나의 스레드만 통과할 수 있는 턴스타일과 같습니다.
- 한 번에 둘 이상의 스레드가 공유 데이터에 액세스하지 않도록 하기 위해 프로세스의 기본 스레드는 전역 CRITICAL_SECTION 데이터 구조를 할당하고 해당 멤버를 초기화합니다. 중요한 섹션을 입력하는 스레드는 EnterCriticalSection 함수를 호출하고 데이터 구조의 멤버를 수정합니다.
- 중요한 섹션을 입력하려는 스레드는 EnterCriticalSection 을 호출하여 CRITICAL_SECTION 데이터 구조가 수정되었는지 확인합니다. 이 경우 다른 스레드가 현재 중요한 섹션에 있고 후속 스레드가 절전 모드로 배치됩니다. 중요한 섹션을 떠나는 스레드는 데이터 구조를 다시 설정하는 LeaveCriticalSection을 호출합니다. 스레드가 중요한 섹션을 벗어나면 시스템에서 절전 모드 스레드 중 하나를 절전 모드에서 해제한 다음, 중요한 섹션으로 들어갑니다.
- 뮤텍스는 다른 프로세스에서 실행되는 스레드가 뮤텍스에 액세스할 수 있다는 점을 제외하고 중요한 섹션과 동일한 함수를 수행합니다. 뮤텍스 개체를 소유하는 것은 토론에 바닥을 갖는 것과 같습니다. 프로세스는 핸들을 반환하는 CreateMutex 함수를 호출하여 뮤텍스 개체를 만듭니다. 뮤텍스 개체를 요청하는 첫 번째 스레드는 뮤텍스 개체의 소유권을 얻습니다. 스레드가 뮤텍스로 완료되면 소유권이 선착순으로 다른 스레드로 전달됩니다.
- 세마포는 사용 가능한 일부 리소스에 대한 참조 수를 유지하는 데 사용됩니다. 스레드는 CreateSemaphore 함수를 호출하고 리소스에 대한 포인터, 초기 리소스 수 및 최대 리소스 수를 전달하여 리소스에 대한 세마포를 만듭니다. 이 함수는 핸들을 반환합니다. 리소스를 요청하는 스레드는 WaitForSingleObject 함수에 대한 호출에서 해당 세마포 핸들을 전달합니다. 세마포 개체는 리소스를 폴링하여 사용할 수 있는지 여부를 확인합니다. 이 경우 세마포는 리소스 수를 감소시키고 대기 스레드를 절전 모드에서 해제합니다. 개수가 0이면 다른 스레드가 리소스를 해제할 때까지 스레드가 절전 모드로 유지되어 세마포가 개수를 1로 증가합니다.
관련 항목