thread_local a unique data for each thread

thread_local a unique data for each thread

One of the primary advantages of utilising threads for concurrency is the ability to quickly and directly transfer data across them, so now that we’ve covered thread creation and management, let’s look at the challenges around shared data.

Consider sharing an apartment with a roommate for a time. If there is just one kitchen, you cannot use the oven at the same time, and if your roommate uses the oven for backyard grilling for an extended period of time, it might be inconvenient if you need to use it. It’s just not going to end well if one of you attempts to grill some sausages while the other bakes a cake.

Now there could be two solutions to the problem,

  1. Use synchronization, where if your friend is cooking you will have to wait until he finishes and vice versa.
  2. Buy a new Oven, for a long-term solution.

thread_local uses a second approach. The thread_local is specified in C++ as a specifier to specify thread-local data, which is produced when the thread is created and destroyed when the thread is likewise killed; hence, thread-local data is also known as thread-local storage.

In the example below, variable i is shared by all threads created, whereas variable j is created for each thread.


#include <iostream>
#include <thread>
#include <atomic>
#include<mutex>

std::mutex mutex_obj;

/// <summary>
/// Variable will be shared by all threads
/// </summary>
std::atomic<int> i = 0;


/// <summary>
/// thread_local:: Each thread have it's own copy of variable
/// </summary>
thread_local std::atomic<int> j = 0;

void thread_func() {
    std::lock_guard<std::mutex> obj(mutex_obj);

    ++i; 
    ++j;
    std::cout <<"Shared variable :: "<< i <<std::endl;
    std::cout << "thread_local :: " << j << std::endl;
}

int main() {
    std::thread t1(thread_func);
    std::thread t2(thread_func);
    std::thread t3(thread_func);

    t1.join();
    t2.join();
    t3.join();

    std::cout << std::endl;
}


////////////////// Output /////////////////////////// 
/*
Shared variable :: 1
thread_local :: 1
Shared variable :: 2
thread_local :: 1
Shared variable :: 3
thread_local :: 1
*/
////////////////////////////////////////////////