Suche…
Syntax
- std :: atomic <T>
- std :: atomic_flag
Bemerkungen
std::atomic
ermöglicht den atomaren Zugriff auf einen TriviallyCopyable-Typ. Es ist implementierungsabhängig, wenn dies über atomare Operationen oder Sperren erfolgt. Der einzige garantierte std::atomic_flag
atomare Typ ist std::atomic_flag
.
Multi-Threaded-Zugriff
Ein atomarer Typ kann verwendet werden, um sicher an einem Speicherplatz zu lesen und zu schreiben, der von zwei Threads gemeinsam genutzt wird.
Ein schlechtes Beispiel, das wahrscheinlich zu einem Datenrennen führt:
#include <thread>
#include <iostream>
//function will add all values including and between 'a' and 'b' to 'result'
void add(int a, int b, int * result) {
for (int i = a; i <= b; i++) {
*result += i;
}
}
int main() {
//a primitive data type has no thread safety
int shared = 0;
//create a thread that may run parallel to the 'main' thread
//the thread will run the function 'add' defined above with paramters a = 1, b = 100, result = &shared
//analogous to 'add(1,100, &shared);'
std::thread addingThread(add, 1, 100, &shared);
//attempt to print the value of 'shared' to console
//main will keep repeating this until the addingThread becomes joinable
while (!addingThread.joinable()) {
//this may cause undefined behavior or print a corrupted value
//if the addingThread tries to write to 'shared' while the main thread is reading it
std::cout << shared << std::endl;
}
//rejoin the thread at the end of execution for cleaning purposes
addingThread.join();
return 0;
}
Das obige Beispiel kann zu einem fehlerhaften Lesen führen und kann zu undefiniertem Verhalten führen.
Ein Beispiel mit Thread-Sicherheit:
#include <atomic>
#include <thread>
#include <iostream>
//function will add all values including and between 'a' and 'b' to 'result'
void add(int a, int b, std::atomic<int> * result) {
for (int i = a; i <= b; i++) {
//atomically add 'i' to result
result->fetch_add(i);
}
}
int main() {
//atomic template used to store non-atomic objects
std::atomic<int> shared = 0;
//create a thread that may run parallel to the 'main' thread
//the thread will run the function 'add' defined above with paramters a = 1, b = 100, result = &shared
//analogous to 'add(1,100, &shared);'
std::thread addingThread(add, 1, 10000, &shared);
//print the value of 'shared' to console
//main will keep repeating this until the addingThread becomes joinable
while (!addingThread.joinable()) {
//safe way to read the value of shared atomically for thread safe read
std::cout << shared.load() << std::endl;
}
//rejoin the thread at the end of execution for cleaning purposes
addingThread.join();
return 0;
}
Das obige Beispiel ist sicher, da alle store()
und load()
Operationen des atomic
Datentyps das gekapselte int
vor dem gleichzeitigen Zugriff schützen.