Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CPlusPlusNotesForProfessionals.pdf
Скачиваний:
47
Добавлен:
20.05.2023
Размер:
5.11 Mб
Скачать

Chapter 89: Atomic Types

Section 89.1: Multi-threaded Access

An atomic type can be used to safely read and write to a memory location shared between two threads. A Bad example that is likely to cause a data race:

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

}

The above example may cause a corrupted read and can lead to undefined behavior.

An example with thread safety:

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

}

GoalKicker.com – C++ Notes for Professionals

468

}

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 parameters 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;

}

The above example is safe because all store() and load() operations of the atomic data type protect the

encapsulated int from simultaneous access.

GoalKicker.com – C++ Notes for Professionals

469