One-Time 초기화
구성 요소는 로드될 때가 아니라 처음 호출될 때 초기화 작업을 수행하도록 디자인되는 경우가 많습니다. 일회성 초기화 함수는 여러 스레드가 초기화를 시도할 수 있는 경우에도 이 초기화가 한 번만 발생하도록 합니다.
Windows Server 2003 및 Windows XP: 애플리케이션은 상호 잠긴 함수 또는 기타 동기화 메커니즘을 사용하여 일회성 초기화를 위한 자체 동기화를 제공해야 합니다. 일회성 초기화 함수는 Windows Vista 및 Windows Server 2008부터 사용할 수 있습니다.
일회성 초기화 함수는 하나의 스레드만 초기화를 수행하도록 하는 상당한 이점을 제공합니다.
- 속도에 최적화되어 있습니다.
- 프로세서 아키텍처에 필요한 적절한 장벽을 만듭니다.
- 잠긴 초기화와 병렬 초기화를 모두 지원합니다.
- 코드가 비동기적으로 또는 동기적으로 작동할 수 있도록 내부 잠금을 방지합니다.
시스템은 데이터 및 상태 정보를 포함하는 불투명 한 INIT_ONCE 구조를 통해 초기화 프로세스를 관리합니다. 호출자는 이 구조를 할당하고 InitOnceInitialize 를 호출하거나(구조체를 동적으로 초기화하기 위해) 구조 변수에 상수 INIT_ONCE_STATIC_INIT 할당하여 초기화합니다(구조체를 정적으로 초기화). 처음에 일회성 초기화 구조에 저장된 데이터는 NULL이고 해당 상태는 초기화되지 않습니다.
일회성 초기화 구조는 프로세스 간에 공유할 수 없습니다.
초기화를 수행하는 스레드는 필요에 따라 초기화가 완료된 후 호출자가 사용할 수 있는 컨텍스트를 설정할 수 있습니다. 컨텍스트는 동기화 개체이거나 값 또는 데이터 구조일 수 있습니다. 컨텍스트가 값인 경우 하위 순서 INIT_ONCE_CTX_RESERVED_BITS 0이어야 합니다. 컨텍스트가 데이터 구조인 경우 데이터 구조는 DWORD 정렬이어야 합니다. 컨텍스트는 InitOnceBeginInitialize 또는 InitOnceExecuteOnce 함수의 lpContext 출력 매개 변수에서 호출자에게 반환됩니다.
일회성 초기화는 동기적으로 또는 비동기적으로 수행할 수 있습니다. 선택적 콜백 함수는 동기 일회성 초기화에 사용할 수 있습니다.
동기 일회성 초기화
다음 단계에서는 콜백 함수를 사용하지 않는 동기 일회성 초기화에 대해 설명합니다.
- InitOnceBeginInitialize 함수를 호출하는 첫 번째 스레드는 일회성 초기화를 성공적으로 시작합니다. 동기 일회성 초기화의 경우 INIT_ONCE_ASYNC 플래그 없이 InitOnceBeginInitialize를 호출해야 합니다.
- 초기화를 시도하는 후속 스레드는 첫 번째 스레드가 초기화를 완료하거나 실패할 때까지 차단됩니다. 첫 번째 스레드가 실패하면 다음 스레드가 초기화 등을 시도할 수 있습니다.
- 초기화가 완료되면 스레드는 InitOnceComplete 함수를 호출합니다. 스레드는 필요에 따라 동기화 개체(또는 기타 컨텍스트 데이터)를 만들고 InitOnceComplete 함수의 lpContext 매개 변수에 지정할 수 있습니다.
- 초기화에 성공하면 일회성 초기화 구조의 상태가 초기화됨으로 변경되고 lpContext 핸들(있는 경우)이 초기화 구조에 저장됩니다. 후속 초기화 시도는 이 컨텍스트 데이터를 반환합니다. 초기화에 실패하면 데이터는 NULL입니다.
다음 단계에서는 콜백 함수를 사용하는 동기 일회성 초기화에 대해 설명합니다.
- InitOnceExecuteOnce 함수를 성공적으로 호출하는 첫 번째 스레드는 애플리케이션에서 정의한 InitOnceCallback 콜백 함수 및 콜백 함수에 필요한 모든 데이터에 대한 포인터를 전달합니다. 호출이 성공하면 InitOnceCallback 콜백 함수가 실행됩니다.
- 초기화를 시도하는 후속 스레드는 첫 번째 스레드가 초기화를 완료하거나 실패할 때까지 차단됩니다. 첫 번째 스레드가 실패하면 다음 스레드가 초기화 등을 시도할 수 있습니다.
- 초기화가 완료되면 콜백 함수가 반환됩니다. 콜백 함수는 필요에 따라 동기화 개체(또는 기타 컨텍스트 데이터)를 만들고 컨텍스트 출력 매개 변수에 지정할 수 있습니다.
- 초기화에 성공하면 일회성 초기화 구조의 상태가 초기화됨으로 변경되고 컨텍스트 핸들(있는 경우)이 초기화 구조에 저장됩니다. 후속 초기화 시도는 이 컨텍스트 데이터를 반환합니다. 초기화에 실패하면 데이터는 NULL입니다.
비동기 일회성 초기화
다음 단계에서는 비동기 일회성 초기화를 설명합니다.
- 여러 스레드가 INIT_ONCE_ASYNCInitOnceBeginInitialize를 호출하여 동시에 초기화를 시작하려고 하면 fPending 매개 변수가 TRUE로 설정된 모든 스레드에 대해 함수가 성공합니다. 실제로 초기화 시 하나의 스레드만 성공합니다. 다른 동시 시도는 초기화 상태를 변경하지 않습니다.
-
InitOnceBeginInitialize가 반환되면 fPending 매개 변수는 초기화 상태 나타냅니다.
- fPending이 FALSE이면 초기화 시 하나의 스레드가 성공합니다. 다른 스레드는 만든 컨텍스트 데이터를 클린 InitOnceBeginInitialize의 lpContext 출력 매개 변수에서 컨텍스트 데이터를 사용해야 합니다.
- fPending이 TRUE이면 초기화가 아직 완료되지 않았으며 다른 스레드는 계속되어야 합니다.
- 각 스레드는 InitOnceComplete 함수를 호출합니다. 스레드는 필요에 따라 동기화 개체(또는 기타 컨텍스트 데이터)를 만들고 InitOnceComplete의 lpContext 매개 변수에 지정할 수 있습니다.
-
InitOnceComplete가 반환되면 반환 값은 호출 스레드가 초기화에 성공했는지 여부를 나타냅니다.
- InitOnceComplete가 성공하면 초기화 시 호출 스레드가 성공합니다. 일회성 초기화 구조의 상태가 초기화됨으로 변경되고 lpContext 핸들(있는 경우)이 초기화 구조에 저장됩니다.
- InitOnceComplete가 실패하면 초기화 시 다른 스레드가 성공합니다. 호출 스레드는 만든 컨텍스트 데이터를 클린 InitOnceBeginInitialize를 INIT_ONCE_CHECK_ONLY 호출하여 일회성 초기화 구조에 저장된 컨텍스트 데이터를 검색해야 합니다.
여러 사이트에서 One-Time 초기화 호출
단일 INIT_ONCE 구조로 보호되는 일회성 초기화는 뮤티플 사이트에서 수행할 수 있습니다. 각 사이트에서 서로 다른 콜백을 전달할 수 있으며 콜백을 사용 및 사용하지 않는 동기화가 혼합될 수 있습니다. 초기화는 여전히 한 번만 수행하도록 보증됩니다.
그러나 비동기 및 동기 초기화를 혼합할 수 없습니다. 비동기 초기화를 시도하면 동기 초기화를 시작하려고 하면 실패합니다.
관련 항목