1

I considered thread_local variables as private variables for each thread, just with the same name. But all examples I found use a mutex variable to lock the thread_local variable when accessing it. This confused me. If thread_local is private for each thread, there is no need to take care of the concurrency problem, or my acknowledgement of the "private" idea is wrong?

Example taken from here:

#include <iostream>
#include <string>
#include <thread>
#include <mutex>

thread_local unsigned int rage = 1; 
std::mutex cout_mutex;

void increase_rage(const std::string& thread_name)
{
    ++rage;
    std::lock_guard<std::mutex> lock(cout_mutex);
    std::cout << "Rage counter for " << thread_name << ": " << rage << '\n';
}

int main()
{
    std::thread a(increase_rage, "a"), b(increase_rage, "b");
    increase_rage("main");

    a.join();
    b.join();
}

In this case, is it necessary to lock the thread_local variable?

edmz
  • 8,220
  • 2
  • 26
  • 45
  • 2
    Which example? If you show it we might tell you why it uses a mutex, there might be a different reason for it. – AliciaBytes Aug 08 '15 at 10:05
  • @RaphaelMiedl I got one:http://stackoverflow.com/a/15698197/2269707 –  Aug 08 '15 at 10:22
  • 3
    The `mutex` there is only to synchronize the output through `std::cout` (`std::cout` isn't thread safe and could interleave the output) like the name suggests, it has nothing to do with the thread_local variables. You can see by the output that the thread_local variables are completely distinct. – AliciaBytes Aug 08 '15 at 10:26
  • 2
    The mutex also gets locked **AFTER** the `++rage`, the thread_local variable isn't protected at all and doesn't need to either. – AliciaBytes Aug 08 '15 at 10:28
  • @RaphaelMiedl agree with you the mutex is for synchronizing `cout` – Vinay Shukla Aug 08 '15 at 10:29
  • @RaphaelMiedl thanks so much. So can I get the conclusion that `thread_local` variables do not need to be synchronised? –  Aug 08 '15 at 10:39
  • 1
    Yes, `thread_local` variables don't need to be synchronized. The mutex was absolutely only necessary for the cout in your example. – AliciaBytes Aug 08 '15 at 10:41
  • @RaphaelMiedl thanks, so helpful. –  Aug 08 '15 at 10:45
  • The explanation in http://stackoverflow.com/questions/11983875/what-does-the-thread-local-mean-in-c11 should be very helpful in understanding what's going on here. – Sam Varshavchik Aug 08 '15 at 12:13

2 Answers2

3

If you take a pointer to a thread_local object, and pass the pointer to another thread, in some way, the other thread can still access the original thread's thread_local object using the pointer (until the originating thread terminates, after which point this becames undefined behavior).

So, if this can happen in your application, you will still need to arrange for mutex protection, or something equivalent, in order to access the thread_local object in a thread-safe manner.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
0

Naming thread_local variables private variables is a bit unfortunate.

A thread_local declared variable is owned by its thread and not accessible by other threads unless the owner thread (for some reason) gives them a pointer to that variable. A thread_local variable is shared among all functions of its thread; i.e. it has its lifetime. If a thread_local variable is constructed it will be destroyed when its thread exits.

A thread_local variable can be static, in which case some care should be taken to make sure the program executes as expected. I won't go into this, since it is not part of the question.

The mutex in your example, as pointed out in the comments, is not for a data race condition. It is to synchronize the console output: the mutex is called cout_mutex - self explaining.

Ely
  • 10,860
  • 4
  • 43
  • 64