Online Book Reader

Home Category

Professional C__ - Marc Gregoire [387]

By Root 1341 0

Result = 84157

Result = 77133

Result = 74325

This code is clearly showing race condition behavior. In this example, the best and recommended solution is to use the new atomic types. The following code highlights the required changes:

#include

#include

#include

#include

#include

void func(std::atomic& counter)

{

for (int i = 0; i < 10000; ++i) {

++counter;

}

}

int main()

{

std::atomic counter(0);

std::vector threads;

for (int i = 0; i < 10; ++i) {

threads.push_back(std::thread{func, std::ref(counter)});

}

for (auto& t : threads) {

t.join();

}

std::cout << "Result = " << counter << std::endl;

return 0;

}

Code snippet from atomic\inc_func_atomic.cpp

The changes add the header file, and change the type of the shared counter to std::atomic instead of int. When you run the new example, you will always get 100.000 as the result:

Result = 100000

Result = 100000

Result = 100000

Result = 100000

Result = 100000

Without explicitly adding any locks to your code, you have made it thread-safe and race condition free because the ++counter operation on an atomic type will load the value, increment the value, and store the value in one atomic transaction, which cannot be interrupted.

If you want to compile multithreaded code with GCC, you have to link with the pthread library. For example:

> gcc -lstdc++ -lpthread inc_func_atomic.cpp

Atomic Operations

The C++11 standard defines a number of atomic operations. This section describes a few of those operations. For a full list, consult the Standard Library Reference resource on the website, www.wrox.com.

An example of an atomic operation is:

bool atomic_compare_exchange_strong(atomic* object, C* expected, C desired);

This operation can also be called as a member of atomic:

bool atomic::compare_exchange_strong(C* expected, C desired);

This operation implements the following logic atomically:

if (memcmp(object, expected, sizeof(*object)) == 0) {

memcpy(object, &desired, sizeof(*object));

return true;

} else {

memcpy(expected, object, sizeof(*object));

return false;

}

A second example is atomic::fetch_add(), which fetches the current value of an atomic type, adds the given increment to the atomic value, and returns the original non-incremented value. For example:

atomic value(10);

cout << "Value = " << value << endl;

int fetched = value.fetch_add(4);

cout << "Fetched = " << fetched << endl;

cout << "Value = " << value << endl;

Code snippet from atomic\fetch_add.cpp

If no other threads are touching the contents of the fetched and value variables, the output is as follows:

Value = 10

Fetched = 10

Value = 14

Atomic integral types support the following atomic operations: fetch_add(), fetch_sub(), fetch_and(), fetch_or(), fetch_xor(), ++, --, +=, -=, &=, ^= and |=. Atomic pointer types support fetch_add(), fetch_sub(), ++, --, += and -=.

Most of the atomic operations can accept an extra parameter specifying the memory ordering that you would like. For example:

T atomic::fetch_add(T value, memory_order = memory_order_seq_cst);

You may change the default memory_order. The standard provides: memory_order_relaxed, memory_order_consume, memory_order_acquire, memory_order_release, memory_order_acq_rel and memory_order_seq_cst, all defined in the std namespace. However, it is rare that you will want to use them instead of the default. While another memory order may perform better than the default, according to some metric, if you use them slightly wrong you will again introduce race conditions or other difficult-to-track threading-related problems. If you do need to know more about memory ordering, consult one of the multithreading references in Appendix B.

THREADS


The C++11 threading library, defined in the header file, makes it very easy to launch new threads. Specifying what needs to be executed in the new thread can be done in several ways. You can let the new thread execute a global function, the operator()

Return Main Page Previous Page Next Page

®Online Book Reader