İş Parçacığı Yerel Depolaması (TLS)

İş Parçacığı Yerel Depolama (TLS), belirli bir çok iş parçacıklı işlemdeki her iş parçacığının iş parçacığına özgü verilerin depolandığı konumları ayırabileceği yöntemdir. Dinamik olarak bağlı (çalışma zamanı) iş parçacığına özgü veriler TLS API(TlsAlloc) yoluyla desteklenir. Win32 ve Microsoft C++ derleyicisi artık mevcut API uygulamasına ek olarak iş parçacığı başına statik olarak bağlı (yük süresi) verilerini de destekliyor.

TLS için Derleyici Uygulaması

C++11: thread_local Depolama sınıfı tanımlayıcısı, nesneler ve sınıf üyeleri için iş parçacığı yerel depolamasını belirtmenin önerilen yoludur. Daha fazla bilgi için bkz. Depolama sınıfları (C++).

MSVC, genişletilmiş depolama sınıfı değiştiricisi olarak Microsoft'a özgü bir öznitelik, iş parçacığı da sağlar. Değişken bildirmek thread için anahtar sözcüğünü __declspec kullanın. Örneğin, aşağıdaki kod bir tamsayı iş parçacığı yerel değişkenini bildirir ve bunu bir değerle başlatır:

__declspec( thread ) int tls_i = 1;

Kurallar ve sınırlamalar

Statik olarak bağlı iş parçacığı yerel nesneleri ve değişkenleri bildirildiğinde aşağıdaki yönergelere uyulmalıdır. Bu yönergeler hem iş parçacığı hem de thread_local için geçerlidir:

  • thread özniteliği yalnızca sınıfa ve veri bildirimlerine ve tanımlarına uygulanabilir. İşlev bildirimlerinde veya tanımlarında kullanılamaz. Örneğin, aşağıdaki kod bir derleyici hatası oluşturur:

    __declspec( thread )void func();     // This will generate an error.
    
  • Değiştirici thread yalnızca uzantılı static veri öğelerinde belirtilebilir. Bu, genel veri nesnelerini (hem hem de static extern), yerel statik nesneleri ve C++ sınıflarının statik veri üyelerini içerir. Otomatik veri nesneleri özniteliğiyle thread bildirilemiyor. Aşağıdaki kod derleyici hataları oluşturur:

    void func1()
    {
        __declspec( thread )int tls_i;            // This will generate an error.
    }
    
    int func2(__declspec( thread )int tls_i )     // This will generate an error.
    {
        return tls_i;
    }
    
  • Bildirimlerin ve bir iş parçacığı yerel nesnesinin tanımının tümü özniteliğini thread belirtmelidir. Örneğin, aşağıdaki kod bir hata oluşturur:

    #define Thread  __declspec( thread )
    extern int tls_i;        // This will generate an error, since the
    int __declspec( thread )tls_i;        // declaration and definition differ.
    
  • thread Özniteliği tür değiştirici olarak kullanılamaz. Örneğin, aşağıdaki kod bir derleyici hatası oluşturur:

    char __declspec( thread ) *ch;        // Error
    
  • özniteliğini kullanan C++ nesnelerinin bildirimine izin verildiğinden thread , aşağıdaki iki örnek anlamsal olarak eşdeğerdir:

    __declspec( thread ) class B
    {
    // Code
    } BObject;  // OK--BObject is declared thread local.
    
    class B
    {
    // Code
    };
    __declspec( thread ) B BObject;  // OK--BObject is declared thread local.
    
  • İş parçacığı yerel nesnesinin adresi sabit olarak kabul edilmez ve böyle bir adresi içeren ifadeler sabit ifade olarak kabul edilmez. Standart C'de bunun etkisi, bir iş parçacığı yerel değişkeninin adresinin bir nesne veya işaretçi için başlatıcı olarak kullanılmasına izin vermemektir. Örneğin, aşağıdaki kod C derleyicisi tarafından hata olarak işaretlenir:

    __declspec( thread ) int tls_i;
    int *p = &tls_i;       //This will generate an error in C.
    

    Bu kısıtlama C++'da geçerli değildir. C++ tüm nesnelerin dinamik olarak başlatılmasına izin verdiğinden, bir iş parçacığı yerel değişkeninin adresini kullanan bir ifade kullanarak bir nesneyi başlatabilirsiniz. Aynı iş parçacığı yerel nesnelerinin yapımı gibi yapılır. Örneğin, daha önce gösterilen kod C++ kaynak dosyası olarak derlendiğinde hata oluşturmaz. İş parçacığı yerel değişkeninin adresi, yalnızca adresin alındığı iş parçacığı hala mevcut olduğu sürece geçerlidir.

  • Standart C, yalnızca statik olmayan ölçüdeki nesneler için, kendisine başvuru içeren bir ifadeyle bir nesnenin veya değişkenin başlatılmasını sağlar. C++ genellikle kendisine başvuru içeren bir ifadeyle nesnelerin dinamik olarak başlatılmasına izin vermesine rağmen, iş parçacığı yerel nesnelerinde bu tür bir başlatmaya izin verilmez. Örneğin:

    __declspec( thread )int tls_i = tls_i;                // Error in C and C++
    int j = j;                               // OK in C++, error in C
    __declspec( thread )int tls_i = sizeof( tls_i )       // Legal in C and C++
    

    sizeof Başlatılmakta olan nesneyi içeren bir ifade kendisine bir başvuruyu temsil etmez ve hem C hem de C++'da etkinleştirilir.

    C++, iş parçacığı yerel depolama tesisinde gelecekteki olası geliştirmeler nedeniyle iş parçacığı verilerinin dinamik olarak başlatılmasına izin vermez.

  • Windows Vista'nın __declspec( thread ) önceki Windows işletim sistemlerinde bazı sınırlamalar vardır. DLL herhangi bir veri veya nesneyi olarak __declspec( thread )bildirirse, dinamik olarak yüklenirse bir koruma hatasına neden olabilir. DLL LoadLibrary ile yüklendikten sonra, kod verilere her başvursa sistem hatasına __declspec( thread ) neden olur. bir iş parçacığının genel değişken alanı çalışma zamanında ayrıldığından, bu alanın boyutu uygulamanın gereksinimlerini ve statik olarak bağlı tüm DLL'lerin gereksinimlerini hesaplamayı temel alır. kullandığınızda LoadLibrary, ile __declspec( thread )bildirilen iş parçacığı yerel değişkenlerine izin vermek için bu alanı genişletemezsiniz. DLL ile LoadLibraryyükleniyorsa TLS'yi ayırmak için DLL'nizde TlsAlloc gibi TLS API'lerini kullanın.

Ayrıca bkz.

C ve Win32 ile Çoklu İş Parçacığı Kullanımı