Share to: share facebook share twitter share wa share telegram print page

Thread-local storage

In computer programming, thread-local storage (TLS) is a memory management method that uses static or global memory local to a thread. The concept allows storage of data that appears to be global in a system with separate threads.

Many systems impose restrictions on the size of the thread-local memory block, in fact often rather tight limits. On the other hand, if a system can provide at least a memory address (pointer) sized variable thread-local, then this allows the use of arbitrarily sized memory blocks in a thread-local manner, by allocating such a memory block dynamically and storing the memory address of that block in the thread-local variable. On RISC machines, the calling convention often reserves a thread pointer register for this use.

Usage

While the use of global variables is generally discouraged in modern programming, some older operating systems such as UNIX were originally designed for uniprocessor hardware and often use global variables to store important values. An example is the errno used by many functions of the C library. On a modern machine, where multiple threads may be modifying the errno variable, a call of a system function on one thread may overwrite the value previously set by a call of a system function on a different thread, possibly before following code on that different thread could check for the error condition. The solution is to have errno be a variable that looks as if it is global, but is physically stored in a per-thread memory pool, the thread-local storage.

A second use case would be multiple threads accumulating information into a global variable. To avoid a race condition, every access to this global variable would have to be protected by a mutex. Instead, each thread might accumulate into a thread-local variable, thereby eliminating any possibility of a race condition, thereby removing the need for locking. The threads then only have to synchronise a final accumulation from their own thread-local variable into a single global variable.

Windows implementation

The application programming interface (API) function TlsAlloc can be used to obtain an unused TLS slot index; the TLS slot index will then be considered 'used'.

The TlsGetValue and TlsSetValue functions are then used to read and write a memory address to a thread-local variable identified by the TLS slot index. TlsSetValue only affects the variable for the current thread. The TlsFree function can be called to release the TLS slot index.

There is a Win32 Thread Information Block for each thread. One of the entries in this block is the thread-local storage table for that thread.[1] TlsAlloc returns an index to this table, unique per address space, for each call. Each thread has its own copy of the thread-local storage table. Hence, each thread can independently use TlsSetValue(index) and obtain the specified value via TlsGetValue(index), because these set and look up an entry in the thread's own table.

Apart from TlsXxx function family, Windows executables can define a section which is mapped to a different page for each thread of the executing process. Unlike TlsXxx values, these pages can contain arbitrary and valid addresses. These addresses, however, are different for each executing thread and therefore should not be passed to asynchronous functions (which may execute in a different thread) or otherwise passed to code which assume that a virtual address is unique within the whole process. TLS sections are managed using memory paging and its size is quantized to a page size (4kB on x86 machines). Such sections may only be defined inside a main executable of a program - DLLs should not contain such sections, because they are not correctly initialized when loading with LoadLibrary.

Pthreads implementation

In the Pthreads API, memory local to a thread is designated with the term Thread-specific data.

The functions pthread_key_create and pthread_key_delete are used respectively to create and delete a key for thread-specific data. The type of the key is explicitly left opaque and is referred to as pthread_key_t. This key can be seen by all threads. In each thread, the key can be associated with thread-specific data via pthread_setspecific. The data can later be retrieved using pthread_getspecific.

In addition pthread_key_create can optionally accept a destructor function that will automatically be called at thread exit, if the thread-specific data is not NULL. The destructor receives the value associated with the key as parameter so it can perform cleanup actions (close connections, free memory, etc.). Even when a destructor is specified, the program must still call pthread_key_delete to free the thread-specific data at process level (the destructor only frees the data local to the thread).

Language-specific implementation

Apart from relying on programmers to call the appropriate API functions, it is also possible to extend the programming language to support thread local storage (TLS).

C and C++

In C11, the keyword _Thread_local is used for defining thread-local variables. The header <threads.h>, if supported, defines thread_local as a synonym for that keyword. Example usage:

#include <threads.h>
thread_local int foo = 0;

In C11, <threads.h> also defines a number of functions for retrieving, changing, and destructing a thread-local storage, using names starting with tss_. In C23, thread_local itself becomes a keyword.[2]

C++11 introduces the thread_local[3] keyword which can be used in the following cases

  • Namespace level (global) variables
  • File static variables
  • Function static variables
  • Static member variables

Aside from that, various compiler implementations provide specific ways to declare thread-local variables:

On Windows versions before Vista and Server 2008, __declspec(thread) works in DLLs only when those DLLs are bound to the executable, and will not work for those loaded with LoadLibrary() (a protection fault or data corruption may occur).[10]

Common Lisp and other dialects

Common Lisp provides a feature called dynamically scoped variables.

Dynamic variables have a binding which is private to the invocation of a function and all of the children called by that function.

This abstraction naturally maps to thread-specific storage, and Lisp implementations that provide threads do this. Common Lisp has numerous standard dynamic variables, and so threads cannot be sensibly added to an implementation of the language without these variables having thread-local semantics in dynamic binding.

For instance the standard variable *print-base* determines the default radix in which integers are printed. If this variable is overridden, then all enclosing code will print integers in an alternate radix:

;;; function foo and its children will print
;; in hexadecimal:
(let ((*print-base* 16)) (foo))

If functions can execute concurrently on different threads, this binding has to be properly thread-local, otherwise each thread will fight over who controls a global printing radix.

D

In D version 2, all static and global variables are thread-local by default and are declared with syntax similar to "normal" global and static variables in other languages. Global variables must be explicitly requested using the shared keyword:

int threadLocal;  // This is a thread-local variable.
shared int global;  // This is a global variable shared with all threads.

The shared keyword works both as the storage class, and as a type qualifiershared variables are subject to some restrictions which statically enforce data integrity.[13] To declare a "classic" global variable without these restrictions, the unsafe __gshared keyword must be used:[14]

__gshared int global;  // This is a plain old global variable.

Java

In Java, thread-local variables are implemented by the ThreadLocal class object.[15] ThreadLocal holds variable of type T,[15] which is accessible via get/set methods. For example, ThreadLocal variable holding Integer value looks like this:

private static final ThreadLocal<Integer> myThreadLocalInteger = new ThreadLocal<Integer>();

At least for Oracle/OpenJDK, this does not use native thread-local storage in spite of OS threads being used for other aspects of Java threading. Instead, each Thread object stores a (non-thread-safe) map of ThreadLocal objects to their values (as opposed to each ThreadLocal having a map of Thread objects to values and incurring a performance overhead).[16]

.NET languages: C# and others

In .NET Framework languages such as C#, static fields can be marked with the ThreadStatic attribute:[17]: 898 

class FooBar
{
    [ThreadStatic]
    private static int _foo;
}

In .NET Framework 4.0 the System.Threading.ThreadLocal<T> class is available for allocating and lazily loading thread-local variables.[17]: 899 

class FooBar
{
    private static System.Threading.ThreadLocal<int> _foo;
}

Also an API is available for dynamically allocating thread-local variables.[17]: 899–890 

Object Pascal

In Object Pascal (Delphi) or Free Pascal the threadvar reserved keyword can be used instead of 'var' to declare variables using the thread-local storage.

var
   mydata_process: integer;
threadvar
   mydata_threadlocal: integer;

Objective-C

In Cocoa, GNUstep, and OpenStep, each NSThread object has a thread-local dictionary that can be accessed through the thread's threadDictionary method.

NSMutableDictionary *dict = [[NSThread currentThread] threadDictionary];
dict[@"A key"] = @"Some data";

Perl

In Perl threads were added late in the evolution of the language, after a large body of extant code was already present on the Comprehensive Perl Archive Network (CPAN). Thus, threads in Perl by default take their own local storage for all variables, to minimise the impact of threads on extant non-thread-aware code. In Perl, a thread-shared variable can be created using an attribute:

use threads;
use threads::shared;

my $localvar;
my $sharedvar :shared;

PureBasic

In PureBasic thread variables are declared with the keyword Threaded.

Threaded Var

Python

In Python version 2.4 or later, local class in threading module can be used to create thread-local storage.

import threading
mydata = threading.local()
mydata.x = 1

Multiple instances of local class can be created to store different sets of variables.[18] Thus, it is not a singleton.

Ruby

Ruby can create/access thread-local variables using []=/[] methods:

Thread.current[:user_id] = 1

Rust

Thread-local variables can be created in Rust using the thread_local! macro provided by the Rust standard library:

use std::cell::RefCell;
use std::thread;

thread_local!(static FOO: RefCell<u32> = RefCell::new(1));

FOO.with(|f| {
    assert_eq!(*f.borrow(), 1);
    *f.borrow_mut() = 2;
});

// each thread starts out with the initial value of 1, even though this thread already changed its copy of the thread local value to 2
let t = thread::spawn(move || {
    FOO.with(|f| {
        assert_eq!(*f.borrow(), 1);
        *f.borrow_mut() = 3;
    });
});

// wait for the thread to complete and bail out on panic
t.join().unwrap();

// original thread retains the original value of 2 despite the child thread changing the value to 3 for that thread
FOO.with(|f| {
    assert_eq!(*f.borrow(), 2);
});

See also

  • OpenMP — Another shared-memory multiprocessing facility which supports per-thread storage via "Data sharing attribute clauses" (see under §Clauses)

References

  1. ^ Pietrek, Matt (May 2006). "Under the Hood". MSDN. Retrieved 6 April 2010.
  2. ^ "Concurrency support library - cppreference.com". en.cppreference.com.
  3. ^ Section 3.7.2 in C++11 standard
  4. ^ "C-Compiler Information Specific to Sun's Implementation". C User's Guide Sun Studio 8. 2004. 2.3 Thread Local Storage Specifier.
  5. ^ "XL C/C++ compilers". August 2010. Thread-local storage (TLS). Archived from the original on 11 April 2011.
  6. ^ "Thread-Local Storage". GCC 3.3.1 Manual. 2003.
  7. ^ "LLVM 2.0 Release Notes". 23 May 2007. llvm-gcc Improvements.
  8. ^ "Clang Language Extensions - Clang 3.8 documentation". Introduction. This document describes the language extensions provided by Clang. In addition to the language extensions listed here, Clang aims to support a broad range of GCC extensions. Please see the GCC manual for more information on these extensions.
  9. ^ "Intel® C++ Compiler 8.1 for Linux Release Notes For Intel IA-32 and Itanium® Processors" (PDF). 2004. Thread-local Storage. Archived from the original (PDF) on 19 January 2015.
  10. ^ a b Visual Studio 2003: "Thread Local Storage (TLS)". Microsoft Docs. 5 June 2017.
  11. ^ Intel C++ Compiler 10.0 (windows): Thread-local storage
  12. ^ "Attributes in Clang - Clang 3.8 documentation". thread.
  13. ^ Alexandrescu, Andrei (6 July 2010). Chapter 13 - Concurrency. InformIT. p. 3. Retrieved 3 January 2014. {{cite book}}: |website= ignored (help)
  14. ^ Bright, Walter (12 May 2009). "Migrating to Shared". dlang.org. Retrieved 3 January 2014.
  15. ^ a b Bloch 2018, p. 151-155, §Item 33: Consider typesafe heterogeneous containers.
  16. ^ "How is Java's ThreadLocal implemented under the hood?". Stack Overflow. Stack Exchange. Retrieved 27 December 2015.
  17. ^ a b c Albahari 2022.
  18. ^ "cpython/Lib/_threading_local.py at 3.12 · python/cpython". GitHub. Retrieved 25 October 2023.

Bibliography

  • Albahari, Joseph (2022). C# 10 in a Nutshell (First ed.). O'Reilly. ISBN 978-1-098-12195-2.
  • Bloch, Joshua (2018). "Effective Java: Programming Language Guide" (third ed.). Addison-Wesley. ISBN 978-0134685991.


Read other articles:

Unohana dan ampas tahu dialihkan ke halaman ini. Untuk karakter Bleach (manga), lihat Retsu Unohana. Untuk bangunan berkonstruksi rendah di Tiongkok, lihat Proyek ampas tahu. OkaraOkara yang disaring dari sari kedelai buatan rumah.Nama TiongkokTionghoa 豆渣 / 豆腐渣 TranskripsiTionghoa StandarHanyu Pinyindòu zhā / dòufu zhāWade–Gilestou4 cha1 / tou4fu cha1Nama JepangKanji 雪花菜 / 御殻 Kana おから TranskripsiRevised HepburnokaraNama KoreaHangul비지 / 콩비지 Alih EjaanAlih…

RT-20 RT-20 Jenis Senapan rundukSenapan anti materiel Negara asal  Kroasia Sejarah pemakaian Masa penggunaan 1994–sekarang Digunakan oleh Kroasia Spesifikasi Berat 192 kg (423,29 pon) With Scope and Bipod Panjang 1.330 mm (52,4 in) Barrel Length: 920 mm (36,2 in) Peluru 20 × 110mm Mekanisme Bolt-action Kecepatan peluru 850 m/s (2.789 ft/s) Amunisi Single shot, Manual Load Alat bidik Rear: Inbuilt Scope RT-20 adalah senapan …

Donald Trump (kiri) and Billy Bush (kanan) terekam dalam percakapan yang sangat cabul tentang wanita pada tahun 2005. Rekaman dirilis pada Oktober 2016, saat Trump menjadi calon presiden Amerika Serikat. Donald Trump (kiri) and Billy Bush (kanan) terekam dalam percakapan yang sangat cabul tentang wanita pada tahun 2005. Rekaman dirilis pada Oktober 2016, saat Trump menjadi calon presiden Amerika Serikat. Artikel ini bagian dariseri tentangDonald Trump Presiden Amerika Serikat Kepresidenan Transi…

Untuk tikus semak Afrika, lihat Aethomys. Tikus semak Status konservasi Risiko Rendah (IUCN 3.1)[1] Klasifikasi ilmiah Kerajaan: Animalia Filum: Chordata Kelas: Mammalia Ordo: Rodentia Famili: Muridae Subfamili: Murinae Genus: Rattus Spesies: R. fuscipes Nama binomial Rattus fuscipes(Waterhouse, 1839) Distribusi pada tingkat subspesies: merah=R. f. fuscipes; hijau=R. f. greyi, biru=R. f. assimilis, coklat=R. f. coracius Tikus semak (Rattu…

غودفري ستيفن معلومات شخصية الميلاد 22 أغسطس 2000 (العمر 23 سنة)جوس[1]  الطول 1.85 م (6 قدم 1 بوصة) مركز اللعب مدافع الجنسية نيجيريا  معلومات النادي النادي الحالي دينامو تبليسي (معارًا من ياغيلونيا بياويستوك) مسيرة الشباب سنوات فريق Gee-Lec Football Academy المسيرة الاحترافية1 س

ФервакFervaques Країна  Франція Регіон Нормандія  Департамент Кальвадос  Округ Лізьє Кантон Ліваро Код INSEE 14265 Поштові індекси 14140 Координати 49°02′31″ пн. ш. 0°15′18″ сх. д.H G O Висота 73 - 197 м.н.р.м. Площа 10,67 км² Населення 709 (2011-01-01) Густота 66,45 ос./км² Розміщення Влада…

Герб Білгородки Версії Герб за стандартом УГТДеталіНосій Білогородка Герб Білгородки — офіційний геральдичний символ села в передмісті Києва Білгородки. Опис Герб є пурпуровим щитом з лазуровою хвилястою базою, перетятою нитяними золотими хвилястими балками. На цьо

ألعاب القوى في ألعاب البحر الأبيض المتوسط 2022 المدينة المضيفة هران، الجزائر البلد الجزائر  التاريخ 30 يونيو – 3 يوليو الملعب الرئيسي ملعب وهران الأولمبي الرياضة ألعاب القوى  الفعاليات 38 ألعاب البحر الأبيض المتوسط 2022 طرغونة 2018 تارانتو 2026 تعديل مصدري - تعديل   أقيمت مناف…

Indian caste The Rajputs in Gujarat, or Gujarati Rajputs are members of the Rajput community living in the western Indian state of Gujarat. They ruled several dynasties and princely states during the British era. Some Rajput clans of Gujarat have origins from outside regions such as Rajasthan, while others are native to the region.[citation needed] History, clans, and dynasties Solanki dynasty Solanki dynasty map. The Chaulukyas, also known as the Solankis, ruled parts of what are now Gu…

1983 Egyptian filmThe BeggarDirected byAhmed Al-SabaawiWritten bySamir AbdelazimStarringAdel EmamRelease date1983Running time120 minutesCountryEgyptLanguageArabic The Beggar (Arabic: المتسول, translit. Al-Motasawel) is a 1983 Egyptian comedy film directed by Ahmed Al-Sabaawi and starring Adel Emam.[1] Plot Emam plays Hasanin, an uneducated man who leaves his small village to live with his uncle's family in the city. After having no luck keeping a job, he must return to his vi…

Meeting between Donald Trump and Kim Jong Un For the 2019 Trump–Kim summit, see 2019 North Korea–United States Hanoi Summit. Singapore summit redirects here. For the 2015 summit between leaders of mainland China and Taiwan, see Ma–Xi meeting. 2018 North Korea–United States Singapore SummitSingapore SummitLogo used by the United States[1]Logo used by Singapore[2]Kim Jong Un and Donald Trump shaking hands at the start of the summitHost country SingaporeDate12 June 2018…

Building used for Christian religious activities Church house redirects here. For other uses, see Church House. House of Prayer redirects here. For denomination in the conservative holiness movement, see House of Prayer (denomination). Part of a series onChristianity JesusChrist Nativity Baptism Ministry Crucifixion Resurrection Ascension BibleFoundations Old Testament New Testament Gospel Canon Church Creed New Covenant Theology God Trinity Father Son Holy Spirit Apologetics Baptism Christology…

Association football club in Scunthorpe, England Football clubScunthorpe UnitedFull nameScunthorpe United Football ClubNickname(s)The IronFounded1899; 124 years ago (1899)GroundGlanford ParkCapacity9,088ChairmanMichelle HarnessManagerJimmy DeanLeagueNational League North2022–23National League, 23rd of 24 (relegated)WebsiteClub website Home colours Away colours Current season Scunthorpe United Football Club is a professional association football club based in the town of Scunt…

This article includes a list of general references, but it lacks sufficient corresponding inline citations. Please help to improve this article by introducing more precise citations. (December 2020) (Learn how and when to remove this template message) Trinational Eurodistrict of BaselLegal FormAssociation according to local French lawLocationVillage-Neuf, FranceFormation26. January 2007PresidiumMike Keller, municipal president of Binningen, Marion Dammann, district administrator of Lörrach, Jea…

This article has multiple issues. Please help improve it or discuss these issues on the talk page. (Learn how and when to remove these template messages) This article does not cite any sources. Please help improve this article by adding citations to reliable sources. Unsourced material may be challenged and removed.Find sources: Death Domination – news · newspapers · books · scholar · JSTOR (November 2018) (Learn how and when to remove this template messa…

Manga written by Garon Tsuchiya and Nobuaki Minegishi Old BoyCover to Vol. 1オールドボーイ―ルーズ戦記(Ōrudo Bōi Rūzu Senki)GenreAction[1]Psychological thriller[2] MangaWritten byGaron TsuchiyaIllustrated byNobuaki MinegishiPublished byFutabashaEnglish publisherNA: Dark Horse ComicsImprintAction ComicsMagazineManga ActionDemographicSeinenOriginal run1996 – 1998Volumes8 (List of volumes) Live-action films Oldboy (2003) Zinda (2006) Oldboy (2013) Ol…

Philippine television series The Lost RecipeTitle cardGenre Drama Romantic fantasy Written byErwin Caezar BravoDirected byMonti Puno ParungaoStarring Kelvin Miranda Mikee Quintos Opening themeAbutin by Jennifer Maravilla[1]Country of originPhilippinesOriginal languageTagalogNo. of episodes52 (list of episodes)ProductionExecutive producers Mark Anthony B. Norella Lea Reyes CinematographyMark GinolosCamera setupMultiple-camera setupRunning time25-35 minutesProduction companyGMA Public Affa…

This article has multiple issues. Please help improve it or discuss these issues on the talk page. (Learn how and when to remove these template messages) This article needs to be updated. Please help update this article to reflect recent events or newly available information. (July 2015) This article does not cite any sources. Please help improve this article by adding citations to reliable sources. Unsourced material may be challenged and removed.Find sources: Gazprombank Transnistria…

2016 single by J. Cole Everybody DiesSingle by J. ColeReleasedDecember 5, 2016GenreHip hopLength2:41LabelDreamvilleRoc NationSongwriter(s)Jermaine ColeProducer(s)ColeJ. Cole singles chronology Love Yourz (2016) Everybody Dies (2016) False Prophets (2016) Music videoEverybody Dies on YouTube Everybody Dies (stylized in all lowercase) is a single by American rapper J. Cole, released on December 5, 2016 along with his single False Prophets. The two songs were previously previewed on the documentary…

Series of wars in Central America from 1890 to 1906 Totoposte WarsGuatemalan soldiers in Guatemala City in 1903.Date1890 (first war)1903 (second war)1906 (third war)LocationCentral America, mostly in GuatemalaResult Status quo ante bellumBelligerents First Totoposte War  El Salvador First Totoposte War  Guatemala Salvadoran exiles Second Totoposte War  El Salvador Mexico Guatemalan exiles Second Totoposte War  Guatemala Third Totoposte War  El Salvador Mexico Guatemalan …

Kembali kehalaman sebelumnya

Lokasi Pengunjung: 3.147.7.113