Szukaj…


Składnia

  • std :: atomic <T>
  • std :: atomic_flag

Uwagi

std::atomic pozwala na dostęp atomowy do typu TrivialCopyable, zależy to od implementacji, jeśli odbywa się to za pomocą operacji atomowych lub przy użyciu blokad. Jedynym gwarantowanym bezatomowym typem atomowym jest std::atomic_flag .

Dostęp wielowątkowy

Typu atomowego można użyć do bezpiecznego odczytu i zapisu w miejscu pamięci współdzielonym między dwoma wątkami.

Zły przykład, który może spowodować wyścig danych:

#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;
}

Powyższy przykład może spowodować uszkodzenie odczytu i może prowadzić do nieokreślonego zachowania.

Przykład z bezpieczeństwem wątków:

#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;
}

Powyższy przykład jest bezpieczny, ponieważ wszystkie operacje store() i load() typu danych atomic chronią enkapsulowaną int przed jednoczesnym dostępem.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow