Ugrás a tartalomhoz

thread-local storage

A Wikiszótárból, a nyitott szótárból


Főnév

thread-local storage (tsz. thread-local storages)

  1. (informatika) A Thread-local storage (röviden TLS) egy programozási technika, amely lehetővé teszi, hogy minden szálnak saját példánya legyen egy adott változóból. Ez rendkívül hasznos konkurens programozás esetén, amikor el akarjuk kerülni a közös adatokhoz való egyidejű hozzáférést (pl. mutexekkel való szinkronizáció nélkül).



🧠 Mi az a thread-local változó?

Normál esetben a globális vagy statikus változók minden szál számára közösek:

int counter = 0; // minden szál ugyanazt látja

Thread-local változók ezzel szemben:

thread_local int counter = 0; // minden szálnak saját `counter`-e van

🛠️ Használat C++11-től

A C++11 bevezette a thread_local kulcsszót, amely használható:

  • globális,
  • statikus,
  • és lokális változók előtt.

Példa:

#include <iostream>
#include <thread>

thread_local int szalValtozo = 0;

void futas() {
    szalValtozo++;
    std::cout << "Szál ID: " << std::this_thread::get_id()
              << " | Érték: " << szalValtozo << "\n";
}

int main() {
    std::thread t1(futas);
    std::thread t2(futas);
    t1.join();
    t2.join();
}

Példakimenet:

Szál ID: 0x70000dd9c000 | Érték: 1  
Szál ID: 0x70000de1f000 | Érték: 1

Megjegyzés: Bár ugyanaz a változónév (szalValtozo), minden szálnak saját példánya van, független értékkel.



🔐 Miért hasznos?

Probléma TLS megoldása
Globális változók versenyhelyzete Minden szálnak saját példány
Lockolás elkerülése Nem szükséges mutex
Reentrancia és állapotmentesség Biztonságosabb párhuzamosság



🧱 Statikus változók TLS-sel

void fuggveny() {
    static thread_local int valtozo = 0;
    valtozo++;
    std::cout << "Thread-local érték: " << valtozo << std::endl;
}

⚠️ Fontos megjegyzések

  • Nem osztoznak az értéken a szálak.
  • thread_local változók élettartama a szál élettartamához kötött.
  • Destruktorok automatikusan lefutnak, ha van (C++11 óta támogatott).
  • A thread_local változók alapértelmezésben nem inicializálódnak újra minden hívásnál — egyszer jönnek létre szálanként.



🧩 Haladó: TLS osztálytagként

Ha egy osztály statikus változóját szeretnéd minden szál számára külön példányban:

class Logger {
public:
    static thread_local int hivasSzamlalo;
};

thread_local int Logger::hivasSzamlalo = 0;

💥 TLS vs. más szálkezelés

Módszer Előny Hátrány
mutex Több szál megoszthatja ugyanazt az erőforrást Lockolás, lassabb lehet
atomic Gyors, ha csak egyszerű típusokat módosítasz Nem alkalmas komplex típusokra
thread_local Egyszerű, lockmentes Csak szálankénti példányt használható



📚 Valós használati példák

Felhasználási terület Miért használ TLS-t?
Naplózás (logging) Minden szálnak külön log buffer
Random number generator std::mt19937 nem thread-safe
Cache, memoization Szálankénti gyorsítótár
Profilozás Mérések szálankénti eltárolása



🛠 Alternatívák TLS-re

  • POSIX: pthread_key_create, pthread_setspecific, pthread_getspecific
  • Boost.Thread: boost::thread_specific_ptr
  • Windows: __declspec(thread)

De C++11 óta thread_local a javasolt és platformfüggetlen megoldás.



🔚 Összefoglalás

Fogalom Magyarázat
thread_local Minden szálnak saját változó példány
Használat Globális, statikus vagy lokális változóknál
Élettartam Szál kezdete → szál vége
Fő előny Nem kell szinkronizálni, gyors, egyszerű