Threads & Concurrency

thread-local storage

/ TLS (the storage kind, not the network kind) /

Sometimes you want a variable that every thread can refer to by the same name, but where each thread quietly gets its own private copy. Thread-local storage gives you exactly that. Picture a hotel where every room has a thing labelled 'minibar': the label is the same in every room, but each guest's minibar is their own - what one guest takes does not touch another's. A thread-local variable works the same way: one name, but a separate, independent box per thread.

Concretely, a normal global variable is one box shared by all threads (and therefore shared mutable state, with all its hazards). A thread-local variable is declared so the runtime gives each thread its own instance of it; thread A's copy and thread B's copy live at different addresses, and writing one never affects the other. In C11 you mark such a variable with the _Thread_local keyword (C++ uses thread_local); older code uses compiler extensions like __thread. Each thread's copy is created when the thread starts and lives as long as that thread. So you get the convenience of a global - reachable from any function without passing it around - without the sharing, because it is not actually shared.

Why it is useful: thread-local storage is one of the cleanest cures for shared mutable state, because it removes the 'shared' leg entirely. The classic real example is errno: many library functions report errors through errno, and if it were one shared global, two threads' error codes would clobber each other - so on threaded systems errno is thread-local, giving each thread its own. The same trick suits per-thread scratch buffers, counters you total up at the end, or any state that is logically 'this thread's own'. The trade-off is that thread-local data is genuinely separate: it cannot be used to communicate between threads, and each copy costs a little memory.

_Thread_local int call_count = 0; gives every thread its own call_count. Each thread can freely do call_count++ with no lock and no race, because no two threads share the same one - the 'shared' part of shared mutable state is gone.

One name, a private copy per thread - removes the sharing, so no lock is needed.

Thread-local does NOT mean shared-but-safe - it means not shared at all. You cannot pass data between threads through a thread-local variable, and each thread's copy is independent. (This is the storage TLS; do not confuse it with Transport Layer Security, the network TLS.)

Also called
TLSthread-local variable執行緒區域變數執行緒專屬儲存