问题
It is said volatile is needed for signal handler, e.g.,
volatile int flag = 1; // volatile is needed here?
void run() {
while(flag) { /* do someting... */ }
}
void signal_handler(int sig) {
flag = 0;
}
int main() {
signal(SIGINT, sig_handler);
run();
// ...
}
It is said volatile is often not used in multithreading. But how about the similar case like above in multithreading:
int flag = 1; // is volatile needed here?
void thread_function() {
while(flag) { /* do someting... */ }
}
int main() {
// pthread_create() to create thread_function()...
sleep(10); // let thread_function run for 10 seconds
flag = 0;
// ...
}
Should the volatile keyword be used in both cases? Are the two cases treated the same way by compiler?
回答1:
volatile
is used to make sure that the contents of the variable is read from the actual memory rather than from a CPU register.
In other words, whenever an "outside" event might change the value of a variable, you should consider using volatile
("outside" - as in, outside the relevant code block).
In both your examples, you are using the variable as a flag to signal a change in behavior. This flag, in both examples, is controlled by events "outside" the loop that that is reviewing the flag. For this reason, both examples require the use of the volatile
keyword.
It should be noted volatile
does not provide thread safety for a number of reasons. To make sure an object is thread safe, read/write operations must be either protected or atomic.
回答2:
The only non-local values you are allowed to modify from a signal handler are those of type volatile sig_atomic_t
, and atomic types. In particular, writing to your volatile int
is not allowed, and if your signal handler runs you have undefined behaviour.
回答3:
The c++ standard, in [intro.execution], paragraph 6, tells:
When the processing of the abstract machine is interrupted by receipt of a signal, the values of objects which are neither
— of type volatile std::sig_atomic_t nor
— lock-free atomic objects (29.4)
are unspecified during the execution of the signal handler, and the value of any object not in either of these two categories that is modified by the handler becomes undefined.
Therefore, yes, for signal handlers, you have to use volatile std::sig_atomic_t
.
来源:https://stackoverflow.com/questions/42182435/volatile-for-signal-handler-and-multi-threading