In
computer programming
Computer programming or coding is the composition of sequences of instructions, called computer program, programs, that computers can follow to perform tasks. It involves designing and implementing algorithms, step-by-step specifications of proc ...
, thread-local storage (TLS) is a
memory management
Memory management (also dynamic memory management, dynamic storage allocation, or dynamic memory allocation) is a form of Resource management (computing), resource management applied to computer memory. The essential requirement of memory manag ...
method that uses
static or global
memory
Memory is the faculty of the mind by which data or information is encoded, stored, and retrieved when needed. It is the retention of information over time for the purpose of influencing future action. If past events could not be remembe ...
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
In computing, a memory address is a reference to a specific memory location in memory used by both software and hardware. These addresses are fixed-length sequences of digits, typically displayed and handled as unsigned integers. This numeric ...
(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
In electronics and computer science, a reduced instruction set computer (RISC) is a computer architecture designed to simplify the individual instructions given to the computer to accomplish tasks. Compared to the instructions given to a comp ...
machines, the
calling convention
In computer science, a calling convention is an implementation-level (low-level) scheme for how subroutines or functions receive parameters from their caller and how they return a result. When some code calls a function, design choices have been ...
often reserves a thread pointer register for this use.
Usage
While the use of
global variable
In computer programming, a global variable is a variable with global scope, meaning that it is visible (hence accessible) throughout the program, unless shadowed. The set of all global variables is known as the ''global environment'' or ''global ...
s is generally discouraged in modern programming, some older operating systems such as
UNIX
Unix (, ; trademarked as UNIX) is a family of multitasking, multi-user computer operating systems that derive from the original AT&T Unix, whose development started in 1969 at the Bell Labs research center by Ken Thompson, Dennis Ritchie, a ...
were originally designed for
uniprocessor hardware and often use global variables to store important values. An example is the
errno
errno.h is a header file in the standard library of the C programming language. It defines macros for reporting and retrieving error conditions using the symbol errno (short form for "error number").International Standard for Programming Langu ...
used by many functions of the
C library
The C standard library, sometimes referred to as libc, is the standard library for the C programming language, as specified in the ISO C standard.ISO/ IEC (2018). '' ISO/IEC 9899:2018(E): Programming Languages - C §7'' Starting from the origina ...
. 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
A race condition or race hazard is the condition of an electronics, software, or other system where the system's substantive behavior is dependent on the sequence or timing of other uncontrollable events, leading to unexpected or inconsistent ...
, every access to this global variable would have to be protected by a
mutex
In computer science, a lock or mutex (from mutual exclusion) is a synchronization primitive that prevents state from being modified or accessed by multiple threads of execution at once. Locks enforce mutual exclusion concurrency control policies, ...
. 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
An application programming interface (API) is a connection between computers or between computer programs. It is a type of software Interface (computing), interface, offering a service to other pieces of software. A document or standard that des ...
(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.
Each call of
TlsAlloc
returns a unique index into this table. Each thread can independently use
TlsSetValue(index, value)
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
In computer operating systems, memory paging is a memory management scheme that allows the physical memory used by a program to be non-contiguous. This also helps avoid the problem of memory fragmentation and requiring compaction to reduce fr ...
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
In computing, POSIX Threads, commonly known as pthreads, is an execution model that exists independently from a programming language, as well as a parallel execution model. It allows a program to control multiple different flows of work that ov ...
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
, if supported, defines
thread_local
as a synonym for that keyword. Example usage:
#include
thread_local int foo = 0;
In C11,
also defines a number of functions for retrieving, changing, and destructing a thread-local storage, using names starting with . In C23,
thread_local
itself becomes a keyword.
C++11
C++11 is a version of a joint technical standard, ISO/IEC 14882, by the International Organization for Standardization (ISO) and International Electrotechnical Commission (IEC), for the C++ programming language. C++11 replaced the prior vers ...
introduces the
thread_local
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:
*
Solaris Studio
Oracle Developer Studio, formerly named Oracle Solaris Studio, Sun Studio, Sun WorkShop, Forte Developer, and SunPro Compilers, is the Oracle Corporation's flagship software development product for the Solaris and Linux operating systems. It inc ...
C/C++, IBM XL C/C++,
GNU C, llvm-gcc,
Clang
Clang () is a compiler front end for the programming languages C, C++, Objective-C, Objective-C++, and the software frameworks OpenMP, OpenCL, RenderScript, CUDA, SYCL, and HIP. It acts as a drop-in replacement for the GNU Compiler ...
, and
Intel C++ Compiler
Intel oneAPI DPC++/C++ Compiler and Intel C++ Compiler Classic (deprecated icc and icl is in Intel OneAPI HPC toolkit) are Intel’s C, C++, SYCL, and Data Parallel C++ (DPC++) compilers for Intel processor-based systems, available for Wind ...
(Linux systems) use the syntax:
*:
__thread int number;
*
Visual C++
Microsoft Visual C++ (MSVC) is a compiler for the C, C++, C++/CLI and C++/CX programming languages by Microsoft. MSVC is proprietary software; it was originally a standalone product but later became a part of Visual Studio and made available ...
,
[Visual Studio 2003: ] Intel C/C++ (Windows systems),
C++Builder
C++Builder is a rapid application development (RAD) environment for developing software in the C++ programming language. Originally developed by Borland, it is owned by Embarcadero Technologies, a subsidiary of Idera. C++Builder can compile ...
, Clang, and Digital Mars C++ use the syntax:
*:
__declspec(thread) int number;
*C++Builder also supports the syntax:
*:
int __thread number;
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).
Common Lisp and other dialects
Common Lisp
Common Lisp (CL) is a dialect of the Lisp programming language, published in American National Standards Institute (ANSI) standard document ''ANSI INCITS 226-1994 (S2018)'' (formerly ''X3.226-1994 (R1999)''). The Common Lisp HyperSpec, a hyperli ...
provides a feature called
dynamically scoped
In computer programming, the scope of a name binding (an association of a name to an entity, such as a Variable (programming), variable) is the part of a Computer program, program where the name binding is valid; that is, where the name can be use ...
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 qualifier In the context of programming languages, a type qualifier is a keyword that can be used to annotate a type to instruct the compiler to treat the now ''qualified type'' in a special way.
By language
C/C++
and C11, there are four type qualifiers i ...
– ''shared'' variables are subject to some restrictions which statically enforce data integrity. To declare a "classic" global variable without these restrictions, the unsafe ''__gshared'' keyword must be used:
__gshared int global; // This is a plain old global variable.
Java
In
Java
Java is one of the Greater Sunda Islands in Indonesia. It is bordered by the Indian Ocean to the south and the Java Sea (a part of Pacific Ocean) to the north. With a population of 156.9 million people (including Madura) in mid 2024, proje ...
, thread-local variables are implemented by the
class
Class, Classes, or The Class may refer to:
Common uses not otherwise categorized
* Class (biology), a taxonomic rank
* Class (knowledge representation), a collection of individuals or objects
* Class (philosophy), an analytical concept used d ...
object. ThreadLocal holds variable of type T, which is accessible via get/set methods. For example, ThreadLocal variable holding Integer value looks like this:
private static final ThreadLocal myThreadLocalInteger = new ThreadLocal();
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).
.NET languages: C# and others
In
.NET Framework languages such as
C#, static fields can be marked with th
ThreadStatic attribute
class FooBar
In .NET Framework 4.0 th
System.Threading.ThreadLocalclass is available for allocating and lazily loading thread-local variables.
class FooBar
Als
an APIis available for dynamically allocating thread-local variables.
Object Pascal
In
Object Pascal
Object Pascal is an extension to the programming language Pascal (programming language), Pascal that provides object-oriented programming (OOP) features such as Class (computer programming), classes and Method (computer programming), methods.
T ...
(
Delphi
Delphi (; ), in legend previously called Pytho (Πυθώ), was an ancient sacred precinct and the seat of Pythia, the major oracle who was consulted about important decisions throughout the ancient Classical antiquity, classical world. The A ...
) or
Free Pascal
Free Pascal Compiler (FPC) is a compiler for the closely related programming-language dialects Pascal and Object Pascal. It is free software released under the GNU General Public License, witexception clausesthat allow static linking against it ...
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
GNUstep is a free software implementation of the Cocoa (formerly OpenStep) Objective-C frameworks, widget toolkit, and application development tools for Unix-like operating systems and Microsoft Windows. It is part of the GNU Project.
GNUst ...
, and
OpenStep
OpenStep is an object-oriented application programming interface (API) specification developed by NeXT. It provides a framework for building graphical user interfaces (GUIs) and developing software applications. OpenStep was designed to be plat ...
, each
NSThread
object has a thread-local dictionary that can be accessed through the thread's
threadDictionary
method.
NSMutableDictionary *dict = NSThread currentThreadthreadDictionary];
dict "A key"= @"Some data";
Perl
In
Perl
Perl is a high-level, general-purpose, interpreted, dynamic programming language. Though Perl is not officially an acronym, there are various backronyms in use, including "Practical Extraction and Reporting Language".
Perl was developed ...
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
PureBasic is a commercial software, commercially distributed procedural programming, procedural computer programming language and integrated development environment based on BASIC and developed by Fantaisie Software for Microsoft Windows, Windo ...
thread variables are declared with the keywor
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.
Thus, it is not a
singleton.
Ruby
Ruby
Ruby is a pinkish-red-to-blood-red-colored gemstone, a variety of the mineral corundum ( aluminium oxide). Ruby is one of the most popular traditional jewelry gems and is very durable. Other varieties of gem-quality corundum are called sapph ...
can create/access thread-local variables using
[]=
/
[]
methods:
Thread.current[:user_id] = 1
Rust
Thread-local variables can be created in Rust (programming language), Rust using the macro provided by the Rust standard library:
use std::cell::RefCell;
use std::thread;
thread_local!(static FOO: RefCell = RefCell::new(1));
FOO.with(, f, );
// 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 , , );
// 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, );
See also
*
OpenMP
OpenMP is an application programming interface (API) that supports multi-platform shared-memory multiprocessing programming in C, C++, and Fortran, on many platforms, instruction-set architectures and operating systems, including Solaris, ...
— Another shared-memory multiprocessing facility which supports per-thread storage via "Data sharing attribute clauses" (see under
§Clauses)
References
Bibliography
*
*
External links
ELF Handling For Thread-Local Storage— Document about an implementation in
C or
C++.
ACE_TSS< TYPE > Class Template Reference*Article
Use thread-local Storage to Pass Thread Specific Data by
Doug Doedens
Thread-Local Storage by
Lawrence Crowl
*Article
It's Not Always Nice To Share by
Walter Bright
*Practical ThreadLocal usage in Java: http://www.captechconsulting.com/blogs/a-persistence-pattern-using-threadlocal-and-ejb-interceptors
*GCC
*Rust
{{Design Patterns patterns
Threads (computing)
Variable (computer science)
Software design patterns