Example 1
Consider the following basic class:
class X {
int x;
public:
void set_x (int new_x) {x = new_x;}
void get_x () const {return x;}
}
Is set_x
thread safe?
Off course, set_x
is not thread safe as calling it from two threads simultaneously results in a data race.
Is get_x
thread safe?
Two possible reasonings exists:
- Yes, it is thread safe, as calling
get_x
from two threads simultaneously does not result in a data race. - No, it is not thread safe, as calling
get_x
andset_x
from two threads simultaneously results in a data race.
Which one is the correct reasoning?
Example 2
Consider the following related class:
class Y {
int y;
std::mutex m; // mutex added
public:
void set_y (int new_y) {
std::lock_guard<std::mutex> guard(m); // guard setter with mutex
y = new_y;
}
void get_y () const {return y;}
}
Is set_y
thread safe?
Two possible reasonings exists:
- Yes, it is thread safe, as calling
set_y
from two threads simultaneously does not result in a data race. - No, it is not thread safe, as calling
set_y
andget_y
from two threads simultaneously results in a data race.
Which one is the correct reasoning?
Is get_y
thread safe?
Nothing changed: same options as for get_x
.
Correct thread safe class
Off course the correct thread safe implementation is:
class Z {
int z;
mutable std::mutex m; // could be replaced by std::shared_mutex in C++17 (or std::shared_timed_mutex in C++14);
public:
void set_z (int new_z) {
std::lock_guard<std::mutex> guard(m);
z = new_z;
}
void get_z () const {
std::lock_guard<std::mutex> guard(m); // guard getter with mutex
return z;
}
}
Question summary
Which reasoning is correct?
- A function is thread safe iff calling it from two threads simultaneously does not result in a data race. Could work for example 1, but fails in example 2, as this would result to the conclusion that
set_y
andget_y
are thread safe, but classY
isn't as callingset_y
andget_y
from two threads simultaneously results in a data race. - A function is thread safe iff it does not access any memory that could be modified without internal synchronization by another function. This seems to me the most consistent option, but is not the way it is often used (see related threads).
Related threads
Note that I have read the following related threads:
- Does const mean thread-safe in C++11?
- How do I make a function thread safe in C++?
- https://isocpp.org/blog/2012/12/you-dont-know-const-and-mutable-herb-sutter
Aucun commentaire:
Enregistrer un commentaire