다음을 통해 공유


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 출력 매개 변수의 호출자에게 반환됩니다.

일회성 초기화는 동기적으로 또는 비동기적으로 수행할 수 있습니다. 선택적 콜백 함수는 동기 일회성 초기화에 사용할 수 있습니다.

동기 일회성 초기화

다음 단계에서는 콜백 함수를 사용하지 않는 동기 일회성 초기화를 설명합니다.

  1. InitOnceBeginInitialize 함수를 호출하는 첫 번째 스레드는 일회성 초기화를 성공적으로 시작합니다. 동기 일회성 초기화의 경우 InitOnceBeginInitializeINIT_ONCE_ASYNC 플래그 없이 호출해야 합니다.
  2. 초기화를 시도하는 후속 스레드는 첫 번째 스레드가 초기화를 완료하거나 실패할 때까지 차단됩니다. 첫 번째 스레드가 실패하면 다음 스레드가 초기화 등을 시도할 수 있습니다.
  3. 초기화가 완료되면 스레드는 InitOnceComplete 함수를 호출합니다. 스레드는 필요에 따라 동기화 개체(또는 기타 컨텍스트 데이터)를 만들고 InitOnceComplete 함수의 lpContext 매개 변수에 지정할 수 있습니다.
  4. 초기화에 성공하면 일회성 초기화 구조의 상태가 초기화로 변경되고 lpContext 핸들(있는 경우)이 초기화 구조에 저장됩니다. 후속 초기화 시도는 이 컨텍스트 데이터를 반환합니다. 초기화에 실패하면 데이터는 NULL .

다음 단계에서는 콜백 함수를 사용하는 동기 일회성 초기화를 설명합니다.

  1. InitOnceExecuteOnce 함수를 성공적으로 호출하는 첫 번째 스레드는 애플리케이션 정의 InitOnceCallback 콜백 함수 및 콜백 함수에 필요한 모든 데이터에 대한 포인터를 전달합니다. 호출이 성공하면 InitOnceCallback 콜백 함수가 실행됩니다.
  2. 초기화를 시도하는 후속 스레드는 첫 번째 스레드가 초기화를 완료하거나 실패할 때까지 차단됩니다. 첫 번째 스레드가 실패하면 다음 스레드가 초기화 등을 시도할 수 있습니다.
  3. 초기화가 완료되면 콜백 함수가 반환됩니다. 콜백 함수는 필요에 따라 동기화 개체(또는 기타 컨텍스트 데이터)를 만들고 Context 출력 매개 변수에 지정할 수 있습니다.
  4. 초기화에 성공하면 일회성 초기화 구조의 상태가 초기화로 변경되고 컨텍스트 핸들(있는 경우)이 초기화 구조에 저장됩니다. 후속 초기화 시도는 이 컨텍스트 데이터를 반환합니다. 초기화에 실패하면 데이터는 NULL .

비동기 일회성 초기화

다음 단계에서는 비동기 일회성 초기화를 설명합니다.

  1. 여러 스레드가 INIT_ONCE_ASYNCInitOnceBeginInitialize 호출하여 동시에 초기화를 시작하려고 하면 fPending 매개 변수가 TRUE설정된 모든 스레드에 대해 함수가 성공합니다. 실제로는 하나의 스레드만 초기화에 성공합니다. 다른 동시 시도는 초기화 상태를 변경하지 않습니다.
  2. InitOnceBeginInitialize 반환되면 fPending 매개 변수는 초기화 상태를 나타냅니다.
    • fPending false 경우 초기화 시 하나의 스레드가 성공합니다. 다른 스레드는 만든 컨텍스트 데이터를 정리하고 InitOnceBeginInitializelpContext 출력 매개 변수의 컨텍스트 데이터를 사용해야 합니다.
    • fPending TRUE 경우 초기화가 아직 완료되지 않았으며 다른 스레드는 계속되어야 합니다.
  3. 각 스레드는 InitOnceComplete 함수를 호출합니다. 스레드는 필요에 따라 동기화 개체(또는 기타 컨텍스트 데이터)를 만들고 InitOnceCompletelpContext 매개 변수에 지정할 수 있습니다.
  4. InitOnceComplete 반환되면 반환 값은 호출 스레드가 초기화에 성공했는지 여부를 나타냅니다.
    • InitOnceComplete 성공하면 호출 스레드가 초기화에 성공합니다. 일회성 초기화 구조의 상태가 초기화로 변경되고 lpContext 핸들(있는 경우)이 초기화 구조에 저장됩니다.
    • InitOnceComplete 실패하면 초기화 시 다른 스레드가 성공합니다. 호출 스레드는 만든 컨텍스트 데이터를 정리하고 INIT_ONCE_CHECK_ONLY 사용하여 InitOnceBeginInitialize 호출하여 일회성 초기화 구조에 저장된 컨텍스트 데이터를 검색해야 합니다.

여러 사이트에서 One-Time 초기화 호출

단일 INIT_ONCE 구조로 보호되는 일회성 초기화는 여러 사이트에서 수행될 수 있습니다. 각 사이트에서 서로 다른 콜백을 전달할 수 있으며 콜백을 사용 및 사용하지 않는 동기화가 혼합될 수 있습니다. 초기화는 여전히 한 번만 성공적으로 수행되도록 보장됩니다.

그러나 비동기 및 동기 초기화는 혼합할 수 없습니다. 비동기 초기화를 시도하면 동기 초기화를 시작하려는 시도가 실패합니다.

One-Time 초기화 사용