Pamięć lokalna wątku: powiązane z wątkiem pola statyczne i gniazda danych

Do przechowywania danych unikatowych dla wątku i domeny aplikacji można użyć zarządzanego magazynu lokalnego wątku (TLS). Platforma .NET udostępnia dwa sposoby korzystania z zarządzanego protokołu TLS: względne pola statyczne wątku i miejsca danych.

  • Użyj pól statycznych względnych wątków (pól względnych Shared wątków w Visual Basic), jeśli możesz przewidzieć dokładne potrzeby w czasie kompilacji. Pola statyczne względne wątkowo zapewniają najlepszą wydajność. Zapewniają one również korzyści z sprawdzania typów w czasie kompilacji.

  • Użyj miejsc danych, gdy rzeczywiste wymagania mogą zostać odnalezione tylko w czasie wykonywania. Miejsca danych są wolniejsze i bardziej niewygodne do użycia niż pola statyczne względne wątku, a dane są przechowywane jako typ Object, więc przed użyciem należy je rzutować do poprawnego typu.

W niezarządzanym języku C++użyć TlsAlloc polecenia , aby dynamicznie przydzielić miejsca i __declspec(thread) zadeklarować, że zmienna powinna zostać przydzielona w magazynie względnym wątku. Względne pola statyczne wątku i miejsca danych zapewniają zarządzaną wersję tego zachowania.

Możesz użyć System.Threading.ThreadLocal<T> klasy , aby utworzyć obiekty lokalne wątku, które są inicjowane z opóźnieniem, gdy obiekt jest najpierw używany. Aby uzyskać więcej informacji, zobacz Lazy Initialization (Inicjowanie z opóźnieniem).

Unikatowość danych w zarządzanym protokole TLS

Niezależnie od tego, czy używasz względnych pól statycznych wątków, czy miejsc danych w zarządzanym protokole TLS, są unikatowe dla kombinacji domeny wątków i aplikacji.

  • W domenie aplikacji jeden wątek nie może modyfikować danych z innego wątku, nawet jeśli oba wątki używają tego samego pola lub miejsca.

  • Gdy wątek uzyskuje dostęp do tego samego pola lub miejsca z wielu domen aplikacji, w każdej domenie aplikacji jest przechowywana oddzielna wartość.

Jeśli na przykład wątek ustawia wartość pola statycznego względnego wątku, wprowadza inną domenę aplikacji, a następnie pobiera wartość pola, wartość pobrana w drugiej domenie aplikacji różni się od wartości w pierwszej domenie aplikacji. Ustawienie nowej wartości pola w drugiej domenie aplikacji nie wpływa na wartość pola w pierwszej domenie aplikacji.

Podobnie, gdy wątek pobiera to samo nazwane miejsce danych w dwóch różnych domenach aplikacji, dane w pierwszej domenie aplikacji pozostają niezależne od danych w drugiej domenie aplikacji.

Pola statyczne względne wątków

Jeśli wiesz, że element danych jest zawsze unikatowy dla kombinacji wątku i domeny aplikacji, zastosuj ThreadStaticAttribute atrybut do pola statycznego. Użyj pola, ponieważ będzie używane inne pole statyczne. Dane w polu są unikatowe dla każdego wątku, który go używa.

Pola statyczne względne wątkowo zapewniają lepszą wydajność niż miejsca danych i zapewniają korzyść z sprawdzania typów w czasie kompilacji.

Należy pamiętać, że każdy kod konstruktora klasy będzie uruchamiany w pierwszym wątku w pierwszym kontekście, który uzyskuje dostęp do pola. We wszystkich innych wątkach lub kontekstach w tej samej domenie aplikacji pola zostaną zainicjowane do null (Nothing w Visual Basic), jeśli są typami referencyjnymi lub wartościami domyślnymi, jeśli są typami wartości. W związku z tym nie należy polegać na konstruktorach klas do inicjowania pól statycznych względnych wątków. Zamiast tego należy unikać inicjowania pól statycznych względnych wątków i zakładać, że są inicjowane do null (Nothing) lub do ich wartości domyślnych.

Miejsca danych

Platforma .NET udostępnia dynamiczne miejsca danych, które są unikatowe dla kombinacji domeny wątków i aplikacji. Istnieją dwa typy miejsc danych: nazwane miejsca i nienazwane miejsca. Obie są implementowane przy użyciu LocalDataStoreSlot struktury.

W przypadku miejsc nazwanych i nienazwanych użyj Thread.SetData metod i Thread.GetData , aby ustawić i pobrać informacje w miejscu. Są to metody statyczne, które zawsze działają na danych dla aktualnie wykonywanego wątku.

Nazwane miejsca mogą być wygodne, ponieważ można pobrać miejsce, gdy jest on potrzebny, przekazując jego nazwę do GetNamedDataSlot metody, zamiast utrzymywać odwołanie do miejsca bez nazwy. Jeśli jednak inny składnik używa tej samej nazwy magazynu względnego wątku, a wątek wykonuje kod zarówno ze składnika, jak i drugiego składnika, te dwa składniki mogą uszkodzić dane ze sobą. (W tym scenariuszu przyjęto założenie, że oba składniki są uruchomione w tej samej domenie aplikacji i że nie są przeznaczone do udostępniania tych samych danych).

Zobacz też