Udostępnij za pośrednictwem


Obiekty sekcji krytycznej

Obiekt sekcji krytycznej zapewnia synchronizację podobną do tego, która jest dostarczana przez obiekt mutex, z tą różnicą, że sekcja krytyczna może być używana tylko przez wątki pojedynczego procesu. Obiekty sekcji krytycznej nie mogą być współużytkowane przez procesy.

Obiekty zdarzenia, mutex i semaphore mogą być również używane w aplikacji jednoprocesowej, ale obiekty sekcji krytycznej zapewniają nieco szybszy, bardziej wydajny mechanizm synchronizacji wzajemnego wykluczania (test specyficzny dla procesora i instrukcje zestawu). Podobnie jak obiekt mutex, obiekt sekcji krytycznej może być własnością tylko jednego wątku jednocześnie, co ułatwia ochronę zasobu udostępnionego przed równoczesnym dostępem. W przeciwieństwie do obiektu mutex nie ma możliwości ustalenia, czy sekcja krytyczna została porzucona.

Począwszy od systemu Windows Server 2003 z dodatkiem Service Pack 1 (SP1), wątki oczekujące w sekcji krytycznej nie uzyskują sekcji krytycznej w pierwszej kolejności. Ta zmiana znacznie zwiększa wydajność dla większości kodu. Jednak niektóre aplikacje zależą od kolejności pierwszego w poziomie (FIFO) i mogą działać źle lub w ogóle w przypadku bieżących wersji systemu Windows (na przykład aplikacji, które używały krytycznych sekcji jako ogranicznika szybkości). Aby upewnić się, że kod nadal działa prawidłowo, może być konieczne dodanie dodatkowego poziomu synchronizacji. Załóżmy na przykład, że masz wątek producenta i wątek odbiorcy, który używa obiektu sekcji krytycznej do synchronizowania ich pracy. Utwórz dwa obiekty zdarzeń, po jednym dla każdego wątku, aby zasygnalizować, że jest gotowy do kontynuowania drugiego wątku. Wątek odbiorcy będzie czekać, aż producent zasygnalizuje swoje zdarzenie przed wejściem do sekcji krytycznej, a wątek producenta będzie czekać na wątek odbiorcy, aby zasygnalizować jego zdarzenie przed wejściem do sekcji krytycznej. Po opuszczeniu sekcji krytycznej każdy wątek sygnalizuje jego zdarzenie, aby zwolnić drugi wątek.

Windows Server 2003 i Windows XP: Wątki oczekujące w sekcji krytycznej są dodawane do kolejki oczekiwania; są one wybudowane i zazwyczaj uzyskują sekcję krytyczną w kolejności, w której zostały dodane do kolejki. Jeśli jednak wątki są dodawane do tej kolejki z wystarczającą szybkością, wydajność może być obniżona ze względu na czas potrzebny na przebudzenie każdego wątku oczekiwania.

Proces jest odpowiedzialny za przydzielanie pamięci używanej przez sekcję krytyczną. Zazwyczaj odbywa się to przez deklarowanie zmiennej typu CRITICAL_SECTION. Zanim wątki procesu będą mogły go używać, zainicjuj sekcję krytyczną przy użyciu funkcji InitializeCriticalSection lub InitializeCriticalSectionAndSpinCount.

Wątek używa funkcji EnterCriticalSection lub TryEnterCriticalSection, aby zażądać własności sekcji krytycznej. Używa ona funkcji LeaveCriticalSection, aby zwolnić własność sekcji krytycznej. Jeśli obiekt sekcji krytycznej jest obecnie własnością innego wątku, EnterCriticalSection czeka na własność przez czas nieokreślony. Natomiast gdy obiekt mutex jest używany do wzajemnego wykluczania, funkcje oczekiwania zaakceptować określony interwał limitu czasu. Funkcja TryEnterCriticalSection próbuje wprowadzić sekcję krytyczną bez blokowania wątek wywołujący.

Gdy wątek jest właścicielem sekcji krytycznej, może wykonywać dodatkowe wywołania w celu EnterCriticalSection lub TryEnterCriticalSection bez blokowania wykonywania. Zapobiega to zakleszczaniu wątku podczas oczekiwania na sekcję o znaczeniu krytycznym, która jest już właścicielem. Aby zwolnić własność, wątek musi wywołać LeaveCriticalSection raz za każdym razem, gdy wszedł do sekcji krytycznej. Nie ma gwarancji co do kolejności, w której wątki oczekujące nabyją własność sekcji krytycznej.

Wątek używa funkcji InitializeCriticalSectionAndSpinCount lub SetCriticalSectionSpinCount, aby określić liczbę spinów dla obiektu sekcji krytycznej. Spinning oznacza, że gdy wątek próbuje uzyskać sekcję krytyczną, która jest zablokowana, wątek wchodzi w pętlę, sprawdza, czy blokada jest zwolniona, a jeśli blokada nie została zwolniona, wątek przechodzi w stan uśpienia. W systemach z jednym procesorem liczba spinów jest ignorowana, a liczba spinów sekcji krytycznej ma wartość 0 (zero). W systemach wieloprocesorowych, jeśli sekcja krytyczna jest niedostępna, wątek wywołujący uruchamia dwSpinCount razy przed wykonaniem operacji oczekiwania na semaforze skojarzonym z sekcją krytyczną. Jeśli sekcja krytyczna stanie się bezpłatna podczas operacji spin, wątek wywołujący unika operacji oczekiwania.

Każdy wątek procesu może używać funkcji DeleteCriticalSection w celu zwolnienia zasobów systemowych przydzielonych podczas inicjowania obiektu sekcji krytycznej. Po wywołaniu tej funkcji nie można użyć obiektu sekcji krytycznej do synchronizacji.

Gdy obiekt sekcji krytycznej jest własnością, jedynymi innymi wątkami, których dotyczy problem, są wątki oczekujące na własność w wywołaniu EnterCriticalSection. Wątki, które nie oczekują, mogą kontynuować pracę.

obiektów Mutex

używanie obiektów sekcji krytycznej