Atomic operations in C language

1. What is an atomic operation

Atomic operations are indivisible and will not be interrupted by any other tasks or events until they are executed. They can be regarded as the smallest operation unit, which is the smallest operation that does not cause concurrent access to data during execution. Therefore called atomic operations. The simplest atomic operation is to exchange the value of a register and a memory address,

Atomic operations are the basis for implementing the lock mechanism. Mutex, spinlock, etc. all have a key atomic operation at their bottom layer. In programming languages, there are generally two cases:

  1. In a single thread, operations that can be completed in a single instruction can be considered "atomic operations" because interrupts can only occur between instructions
  2. In multithreading, operations that cannot be interrupted by other processes (threads) are called atomic operations

2. Why atomic operations are needed

On a machine with multi-core processors, the memory area for the same variable value may be accessed simultaneously by multiple CPUs within a short period of time, resulting in instability of the value. For example, in multi-threading, initialize i = 0. For the operation i++, if two threads call it at the same time, it may cause the value of i to be 2 when the first thread uses it.

The operation of i++ is divided into three steps:

  1. Memory access, read the value of the i variable into the register of the CPU;
  2. Make the value in the register +1;
  3. Write the value in the register back to memory.

It can be seen that i++ is not an atomic operation. In a multi-threaded processor without thread protection, each step may be interrupted by an external interrupt, thereby affecting the value of i. If two threads call i++ at the same time, i may directly change from 0 to 2 - thread 1 increases i by 1 in the register while thread 2 is also doing this operation, so when the value of i in the register is taken out to memory , i was added 2 times unknowingly

3. Classification of atomic operations

3.1 Hardware-level atomic operations

If it is a single-processor system, any operation can be considered an atomic operation as long as it is completed in a single instruction

In the case of multiple processors, any single instruction operation may be disturbed. The x86 platform CPU provides a means of locking the bus during instruction execution to ensure atomicity

3.2 Software-level atomic operations

The implementation of software-level atomic operations depends on the support of hardware atomic operations. For example, in the Linux environment, the kernel provides two sets of atomic operation interfaces:

  1. operate on integers
  2. operate on bits

4. Atomic operation API


// 将value加到*ptr上,结果更新到*ptr,并返回操作之前*ptr的值
type __sync_fetch_and_add (type *ptr, type value, ...) 

// 从*ptr减去value,结果更新到*ptr,并返回操作之前*ptr的值
type __sync_fetch_and_sub (type *ptr, type value, ...) 

// 将*ptr与value相或,结果更新到*ptr, 并返回操作之前*ptr的值
type __sync_fetch_and_or (type *ptr, type value, ...) 

// 将*ptr与value相与,结果更新到*ptr,并返回操作之前*ptr的值
type __sync_fetch_and_and (type *ptr, type value, ...) 

// 将*ptr与value异或,结果更新到*ptr,并返回操作之前*ptr的值
type __sync_fetch_and_xor (type *ptr, type value, ...) 

// 将*ptr取反后,与value相与,结果更新到*ptr,并返回操作之前*ptr的值
type __sync_fetch_and_nand (type *ptr, type value, ...) 

// 将value加到*ptr上,结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_add_and_fetch (type *ptr, type value, ...) 

// 从*ptr减去value,结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_sub_and_fetch (type *ptr, type value, ...) 

// 将*ptr与value相或, 结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_or_and_fetch (type *ptr, type value, ...) 

// 将*ptr与value相与,结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_and_and_fetch (type *ptr, type value, ...) 

// 将*ptr与value异或,结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_xor_and_fetch (type *ptr, type value, ...) 

// 将*ptr取反后,与value相与,结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_nand_and_fetch (type *ptr, type value, ...) 

// 比较*ptr与oldval的值,如果两者相等,则将newval更新到*ptr并返回true
bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...) 

// 比较*ptr与oldval的值,如果两者相等,则将newval更新到*ptr并返回操作之前*ptr的值
type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...) 

Guess you like

Origin blog.csdn.net/future_sky_word/article/details/128515269