Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

#include <random>

int f() {

    std::random_device seeder;
    std::mt19937 engine(seeder());
    std::uniform_int_distribution<int> dist(1, 6);

    return dist(engine);

}

Can multiple threads call this function safely? Is the function thread safe? It is reduntant to call std::random_device seeder; and std::mt19937 engine(seeder()); every time?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
767 views
Welcome To Ask or Share your Answers For Others

1 Answer

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...