atomic_fetch_add()
is a built-in function defined in the <stdatomic.h>
header. It is included in the C11 version of C.
The following is the function prototype:
C atomic_fetch_add(volatile A* obj, M arg);
We use atomic_fetch_add()
to atomically replace the value pointed to by obj
. The function does this by adding arg
to the previous value of obj
.
Atomic value types only allow reading and writing of variables in a single instruction. This avoids the possibility of multiple threads accessing shared variables in parallel.
The atomic_fetch_add()
function takes the following input arguments:
obj
: pointer to the atomic object to be updated
arg
: value to be added to the old value of obj
The function returns the value previously held by obj
.
volatile
is a type qualifier which assures that access to the variable is atomic.A
represents allatomic object types. Only allow reading and writing of variables in a single instruction. M
represents the non-atomic type corresponding toA
.
#include <stdio.h>#include <threads.h>#include <stdatomic.h>//Declaring global variables to//be shared betweeen threadsatomic_int atomic_count = 0; //atomic variableint non_atomic_count = 0; //non-atomic variableint func(void* input){for(int n = 0; n < 1000; ++n) {atomic_fetch_add(&atomic_count, 1); // atomic updation++non_atomic_count; // non-atomic updation}return 0;}int main(void){thrd_t threads[10];for(int i = 0; i < 10; i++)thrd_create(&threads[i], func, NULL);for(int i = 0; i < 10; i++)thrd_join(threads[i], NULL);printf("The atomic counter is: %d\n", atomic_count);printf("The non-atomic counter is: %d\n", non_atomic_count);}
We begin by declaring two counters, one basic and the other atomic. Both counters are initialized to zero.
In our thread function – func()
– we update both counters by 1. We update the atomic counter using atomic_fetch_add()
.
Finally, we create 10 threads. Each thread should ideally increase the value of the counters by 1000.
The atomic counter is: 10000
The non-atomic counter is: 4875
Next, we set the atomic counter to exactly 10000. This is because each thread accesses the atomic counter in turn and not in parallel.
However, we set the non-atomic variable to an unexpected value due to parallel access by all threads. This causes data to lose its integrity.
Free Resources