No C++ std
type uses global data in a non-thread-safe way. Two unrelated instances of such a type can be accessed in different threads.
By default, one instance of a type cannot be accessed from two threads without synchronization.
You are created local variables. These local variables are unrelated to any other instance of their type. There are no thread safety issues here.
Pseudo-random values are most efficiently produced by having state and reusing it. You are not doing this, so your random number from 1 to 6 will be relatively expensive to create.
std::random_device seeder;
std::mt19937 engine(seeder());
std::uniform_int_distribution<int> dist(1, 6);
return dist(engine);
Your use of std::mt19937
is redundant. You are already creating a random_device
, which could be fed to dist
directly, and then created an engine
from it, then using the engine
. The use of engine
here is useless.
Traditionaly you create an engine
(of some type, like mt19937
) once from a seeder
. You then store the engine
, and repeatedly pass it to distributions.
This does the relatively expensive "real random number" generation once to generate a long series of pseudo-random numbers via engine through distribution.
Note, however, that such use has a cost; you must store the engine
and you must prevent multiple-thread access to it.
The "right" way to do this is to have an object that produces random values for you, and pass it around where you need it. Storing the initial seed used would also permit you to repeat the execution of the set of random numbers involved.
If you don't like the idea of explicitly passing around your random state, you could use a thread_local
(or static
with a mutex
guard).
thread_local std::mt19937 engine(std::random_device{}());
std::uniform_int_distribution<int> dist(1, 6);
return dist(engine);
This creates one engine
per thread, and the engine
is initialized with a value from your random_device
.