다음을 통해 공유


다중 스레딩: MFC 동기화 클래스를 사용하는 방법

다중 스레드 애플리케이션을 작성할 때 스레드 간에 리소스 액세스를 동기화하는 것은 일반적인 문제입니다. 둘 이상의 스레드가 동일한 데이터에 동시에 액세스하면 바람직하지 않고 예측할 수 없는 결과가 발생할 수 있습니다. 예를 들어 한 스레드는 구조체의 내용을 업데이트하는 반면 다른 스레드는 동일한 구조체의 내용을 읽고 있을 수 있습니다. 읽기 스레드가 수신할 데이터(이전 데이터, 새로 작성된 데이터 또는 둘 다 혼합)는 알 수 없습니다. MFC는 이 문제를 해결하는 데 도움이 되는 다양한 동기화 및 동기화 액세스 클래스를 제공합니다. 이 항목에서는 사용 가능한 클래스와 이를 사용하여 일반적인 다중 스레드 애플리케이션에서 스레드로부터 안전한 클래스를 만드는 방법을 설명합니다.

일반적인 다중 스레드 애플리케이션에는 스레드 간에 공유할 리소스를 나타내는 클래스가 있습니다. 제대로 디자인된 완전 스레드로부터 안전한 클래스는 동기화 함수를 호출할 필요가 없습니다. 모든 것이 클래스에 내부적으로 처리되므로 손상될 수 있는 방법이 아니라 클래스를 가장 잘 사용하는 방법에 집중할 수 있습니다. 완전히 스레드로부터 안전한 클래스를 만드는 효과적인 방법은 동기화 클래스를 리소스 클래스에 병합하는 것입니다. 동기화 클래스를 공유 클래스로 병합하는 것은 간단한 프로세스입니다.

예를 들어 연결된 계정 목록을 유지하는 애플리케이션을 사용합니다. 이 애플리케이션을 사용하면 별도의 창에서 최대 3개의 계정을 검사할 수 있지만 특정 시간에는 하나만 업데이트할 수 있습니다. 계정이 업데이트되면 업데이트된 데이터가 네트워크를 통해 데이터 보관으로 전송됩니다.

이 예제 애플리케이션은 세 가지 유형의 동기화 클래스를 모두 사용합니다. 한 번에 최대 3개의 계정을 검사할 수 있으므로 CSemaphore를 사용하여 세 개의 뷰 개체에 대한 액세스를 제한합니다. 네 번째 계정을 보려는 시도가 발생하면 애플리케이션은 처음 세 창 중 하나가 닫히거나 실패할 때까지 기다립니다. 계정이 업데이트되면 애플리케이션은 CCriticalSection을 사용하여 한 번에 하나의 계정만 업데이트되도록 합니다. 업데이트가 성공하면 CEvent에 신호를 표시 합니다. CEvent는 이벤트가 신호를 받을 때까지 기다리는 스레드를 해제합니다. 이 스레드는 새 데이터를 데이터 보관 파일로 보냅니다.

스레드로부터 안전한 클래스 디자인

클래스를 완전히 스레드로부터 안전하게 만들려면 먼저 공유 클래스에 적절한 동기화 클래스를 데이터 멤버로 추가합니다. 이전 계정 관리 예제 CSemaphore 에서는 데이터 멤버가 뷰 클래스에 추가되고, CCriticalSection 데이터 멤버가 연결된 목록 클래스에 추가되고 CEvent , 데이터 멤버가 데이터 스토리지 클래스에 추가됩니다.

다음으로, 클래스의 데이터를 수정하거나 제어된 리소스에 액세스하는 모든 멤버 함수에 동기화 호출을 추가합니다. 각 함수에서 CSingleLock 또는 CMultiLock 개체를 만들고 해당 개체의 Lock 함수를 호출해야 합니다. 잠금 개체가 범위를 벗어나서 소멸되면 개체의 소멸자가 리소스를 해제하여 자동으로 호출 Unlock 합니다. 물론 원하는 경우 직접 전화를 걸 Unlock 수 있습니다.

이러한 방식으로 스레드로부터 안전한 클래스를 디자인하면 다중 스레드 애플리케이션에서 스레드로부터 안전하지 않은 클래스처럼 쉽게 사용할 수 있지만 더 높은 수준의 안전성으로 사용할 수 있습니다. 동기화 개체 및 동기화 액세스 개체를 리소스의 클래스에 캡슐화하면 동기화 코드 유지 관리의 단점 없이 스레드로부터 안전한 프로그래밍의 모든 이점을 얻을 수 있습니다.

다음 코드 예제에서는 공유 리소스 클래스 및 개체에 선언된 데이터 멤버 m_CritSection (형식 CCriticalSection)를 사용하여 이 메서드를 CSingleLock 보여 줍니다. 개체의 주소를 사용하여 개체를 만들어 CSingleLock 공유 리소스(파생CWinThread)의 동기화를 m_CritSection 시도합니다. 리소스를 잠그려고 시도하고, 가져오면 공유 개체에 대한 작업이 수행됩니다. 작업이 완료되면 리소스가 호출 Unlock을 통해 잠금 해제됩니다.

CSingleLock singleLock(&m_CritSection);
singleLock.Lock();
// resource locked
//.usage of shared resource...

singleLock.Unlock();

참고 항목

CCriticalSection다른 MFC 동기화 클래스와 달리 시간 제한 잠금 요청 옵션이 없습니다. 스레드가 해제되기 위한 대기 기간은 무한합니다.

이 방법의 단점은 동기화 개체를 추가하지 않고도 클래스가 동일한 클래스보다 약간 느리다는 것입니다. 또한 둘 이상의 스레드가 개체를 삭제할 가능성이 있는 경우 병합된 방법이 항상 작동하지 않을 수 있습니다. 이 경우 별도의 동기화 개체를 유지하는 것이 좋습니다.

다양한 상황에서 사용할 동기화 클래스를 결정하는 방법에 대한 자세한 내용은 다중 스레딩: 동기화 클래스를 사용하는 경우를 참조 하세요. 동기화에 대한 자세한 내용은 Windows SDK의 동기화를 참조하세요. MFC의 다중 스레딩 지원에 대한 자세한 내용은 C++ 및 MFC를 사용한 다중 스레딩을 참조하세요.

참고 항목

C++ 및 MFC에서 다중 스레딩