Movatterモバイル変換


[0]ホーム

URL:


Jump to content
WikipediaThe Free Encyclopedia
Search

Thread-local storage

From Wikipedia, the free encyclopedia
Method for computer memory management
icon
This articleneeds additional citations forverification. Please helpimprove this article byadding citations to reliable sources. Unsourced material may be challenged and removed.
Find sources: "Thread-local storage" – news ·newspapers ·books ·scholar ·JSTOR
(December 2012) (Learn how and when to remove this message)

Incomputer programming,thread-local storage (TLS) is amemory management method that usesstatic or globalmemory local to athread. 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 amemory 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. OnRISC machines, thecalling convention often reserves athread pointer register for this use.

Usage

[edit]

While the use ofglobal variables is generally discouraged in modern programming, some older operating systems such asUNIX were originally designed foruniprocessor hardware and often use global variables to store important values. An example is theerrno used by many functions of theC library. On a modern machine, where multiple threads may be modifying theerrno 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 haveerrno 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 arace condition, every access to this global variable would have to be protected by amutex. 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

[edit]

Theapplication programming interface (API) functionTlsAlloc can be used to obtain an unusedTLS slot index; theTLS slot index will then be considered 'used'.

TheTlsGetValue andTlsSetValue functions are then used to read and write a memory address to a thread-local variable identified by theTLS slot index.TlsSetValue only affects the variable for the current thread. TheTlsFree function can be called to release theTLS slot index.

There is aWin32 Thread Information Block for each thread. One of the entries in this block is the thread-local storage table for that thread.[1]Each call ofTlsAlloc returns a unique index into this table. Each thread can independently useTlsSetValue(index, value) and obtain the specified value viaTlsGetValue(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 usingmemory 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

[edit]

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

The functionspthread_key_create andpthread_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 aspthread_key_t. This key can be seen by all threads. In each thread, the key can be associated with thread-specific data viapthread_setspecific. The data can later be retrieved usingpthread_getspecific.

In additionpthread_key_create can optionally accept a destructor function that will automatically be called at thread exit, if the thread-specific data is notNULL. 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 callpthread_key_delete to free the thread-specific data at process level (the destructor only frees the data local to the thread).

Language-specific implementation

[edit]

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++

[edit]

InC11, the keyword_Thread_local is used for defining thread-local variables. The header<threads.h>, if supported, definesthread_local as a synonym for that keyword. Example usage:

#include<threads.h>thread_localintfoo=0;

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

C++11 introduces thethread_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 willnot work for those loaded withLoadLibrary() (a protection fault or data corruption may occur).[10]

Common Lisp and other dialects

[edit]

Common Lisp provides a feature calleddynamically 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

[edit]

InD 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 theshared keyword:

intthreadLocal;// This is a thread-local variable.sharedintglobal;// This is a global variable shared with all threads.

Theshared keyword works both as the storage class, and as atype 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]

__gsharedintglobal;// This is a plain old global variable.

Java

[edit]

InJava, thread-local variables are implemented by theThreadLocalclass 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:

privatestaticfinalThreadLocal<Integer>myThreadLocalInteger=newThreadLocal<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

[edit]

In.NET Framework languages such asC#, static fields can be marked with theThreadStatic attribute:[17]: 898 

classFooBar{[ThreadStatic]privatestaticint_foo;}

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

classFooBar{privatestaticSystem.Threading.ThreadLocal<int>_foo;}

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

Object Pascal

[edit]

InObject Pascal (Delphi) orFree Pascal thethreadvar reserved keyword can be used instead of 'var' to declare variables using the thread-local storage.

varmydata_process:integer;threadvarmydata_threadlocal:integer;

Objective-C

[edit]

InCocoa,GNUstep, andOpenStep, eachNSThread object has a thread-local dictionary that can be accessed through the thread'sthreadDictionary method.

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

Perl

[edit]

InPerl threads were added late in the evolution of the language, after a large body of extant code was already present on theComprehensive 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:

usethreads;usethreads::shared;my$localvar;my$sharedvar:shared;

PureBasic

[edit]

InPureBasic thread variables are declared with the keywordThreaded.

Threaded Var

Python

[edit]

InPython version 2.4 or later,local class inthreading module can be used to create thread-local storage.

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

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

Ruby

[edit]

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

Thread.current[:user_id]=1

Rust

[edit]

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

usestd::cell::RefCell;usestd::thread;thread_local!(staticFOO: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 2lett=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 panict.join().unwrap();// original thread retains the original value of 2 despite the child thread changing the value to 3 for that threadFOO.with(|f|{assert_eq!(*f.borrow(),2);});

See also

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

References

[edit]
  1. ^Pietrek, Matt (May 2006)."Under the Hood".Microsoft Systems Journal.11 (5). Archived fromthe original on 9 September 2010. Retrieved6 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 fromthe 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 fromthe original(PDF) on 19 January 2015.
  10. ^abVisual 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".The D Programming Language. InformIT. p. 3. Retrieved3 January 2014.
  14. ^Bright, Walter (12 May 2009)."Migrating to Shared".dlang.org. Retrieved3 January 2014.
  15. ^abBloch 2018, p. 151-155, §Item 33: Consider typesafe heterogeneous containers.
  16. ^"How is Java's ThreadLocal implemented under the hood?".Stack Overflow. Stack Exchange. Retrieved27 December 2015.
  17. ^abcAlbahari 2022.
  18. ^"cpython/Lib/_threading_local.py at 3.12 · python/cpython".GitHub. Retrieved25 October 2023.

Bibliography

[edit]
  • 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.


External links

[edit]
Gang of Four
patterns
Creational
Structural
Behavioral
Concurrency
patterns
Architectural
patterns
Other
patterns
Books
People
Communities
See also
Retrieved from "https://en.wikipedia.org/w/index.php?title=Thread-local_storage&oldid=1274076230"
Categories:
Hidden categories:

[8]ページ先頭

©2009-2026 Movatter.jp