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.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow