C++关键字整理

atomic

#include

原子操作(atomic): 互斥量的加锁一般是针对一个代码段,而原子操作针对的一般都是一个变量。原子变量既不可复制亦不可移动。(1)它表示在多个线程访问同一个全局资源的时候,能够确保所有其他的线程都不在同一时间内访问相同的资源。也就是他确保了在同一时刻只有唯一的线程对这个资源进行访问。这有点类似互斥对象对共享资源的访问的保护,但是原子操作更加接近底层,因而效率更高。是线程安全的。

(2)原子数据类型不会发生数据竞争,能直接用在多线程中而不必我们用户对其进行添加互斥资源锁的类型。从实现上,大家可以理解为这些原子类型内部自己加了锁。

(3)C++11中所有的原子类都是不允许拷贝、不允许Move的,atomic_flag也不例外。

(4)C++11 对常见的原子操作进行了抽象,定义出统一的接口,并根据编译选项/环境产生平台相关的实现。新标准将原子操作定义为atomic模板类的成员函数,囊括了绝大多数典型的操作——读、写、比较、交换等

contained type

atomic type

bool

atomic_bool

char

atomic_char

signed char

atomic_schar

unsigned char

atomic_uchar

short

atomic_short

unsigned short

atomic_ushort

int

atomic_int

unsigned int

atomic_uint

long

atomic_long

unsigned long

atomic_ulong

long long

atomic_llong

unsigned long long

atomic_ullong

wchar_t

atomic_wchar_t

char16_t

atomic_char16_t

char32_t

atomic_char32_t

intmax_t

atomic_intmax_t

uintmax_t

atomic_uintmax_t

int_leastN_t

atomic_int_leastN_t

uint_leastN_t

atomic_uint_leastN_t

int_fastN_t

atomic_int_fastN_t

uint_fastN_t

atomic_uint_fastN_t

intptr_t

atomic_intptr_t

uintptr_t

atomic_uintptr_t

size_t

atomic_size_t

ptrdiff_t

atomic_ptrdiff_t

(4)macro

macro

relative to types

ATOMIC_BOOL_LOCK_FREE

bool

ATOMIC_CHAR_LOCK_FREE

char

signed char

unsigned char

ATOMIC_SHORT_LOCK_FREE

short

unsigned short

ATOMIC_INT_LOCK_FREE

int

unsigned int

ATOMIC_LONG_LOCK_FREE

long

unsigned long

ATOMIC_LLONG_LOCK_FREE

long long

unsigned long long

ATOMIC_WCHAR_T_LOCK_FREE

wchar_t

ATOMIC_CHAR16_T_LOCK_FREE

char16_t

ATOMIC_CHAR32_T_LOCK_FREE

char32_t

ATOMIC_POINTER_LOCK_FREE

U*

(for any type U)

(5)memory_order:内存顺序

序号

意义

1

memory_order_relaxed

宽松模型,不对执行顺序做保证

2

memory_order_consume

当前线程中,满足happens-before原则。

当前线程中该原子的所有后续操作,必须在本条操作完成之后执行

3

memory_order_acquire

当前线程中,读操作满足happens-before原则。

所有后续的读操作必须在本操作完成后执行

4

memory_order_release

当前线程中,写操作满足happens-before原则。

所有后续的写操作必须在本操作完成后执行

5

memory_order_acq_rel

当前线程中,同时满足memory_order_acquire和memory_order_release

6

memory_order_seq_cst

最强约束。全部读写都按顺序执行

(6)Functions

(7)std::atomic的限制:trivially copyable(可平凡复制):一个类型如果是trivially copyable,则使用memcpy这种方式把它的数据从一个地方拷贝出来会得到相同的结果。

1.没有non-trivial 的拷贝构造函数

2.没有non-trivial的move构造函数

3.没有non-trivial的赋值操作符

4.没有non-trivial的move赋值操作符

5.有一个trivial的析构函数

std::atomic_flag:最简单的原子变量实例,是对于bool类型的变量进行原子操作,提供了标志的管理,标志有三种状态:clear、set和未初始化状态。

接口介绍:

(1)ATOMIC_FLAG_INIT:用于给atomic_flag变量赋初值,如果定义后为赋值,则状态是不确定的。被这个赋值后的状态为false。

(2)test_and_set() :接口函数,调用后状态变为true,并返回改变状态前的状态值。

(3)clear() : 接口函数,调用后状态变为false。

#include

#include

#include

#include

std::atomic_flag lock = ATOMIC_FLAG_INIT;

int gcnt = 0;

void f(int n)

{

for (int cnt = 0; cnt < 100; ++cnt) {

while (lock.test_and_set(std::memory_order_acquire)) // 获得锁

; // 自旋

std::cout << "Output from thread " << n << '';

gcnt++;

lock.clear(std::memory_order_release); // 释放锁

}

}

int main()

{

std::vector v;

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

v.emplace_back(f, n);

}

for (auto& t : v) {

t.join();

}

}

自旋锁的解释:当某一个线程调用‘lock.test_and_set’时,即设置lock的状态为true,当另一个线程进入时,再次调用test_and_set时返回的状态为true,则一直在while循环中不断获取,即实现了等待,直到第一个线程调用clear将状态变为false。

std::atomic:通过atomic模板类可以对更多的类型进行原子操作

(1)is_lock_free:通过这个接口判断是否需要加锁。如果是,则在多个线程访问该对象时不会导致线程阻塞(可能使用某种事务内存transactional memory方法实现lock-free的特性)。事实上该函数可以做为一个静态函数。所有指定相同类型T的atomic实例的is_lock_free函数都会返回相同值。

(2)store:赋值操作。operator=实际上内部调用了store,并返回d。

void store(T desr, memory_order m = memory_order_seq_cst) noexcept;void store(T desr, memory_order m = memory_order_seq_cst) volatile noexcept;T operator=(T d) noexcept;T operator=(T d) volatile noexcept;

(3)load: 读取,加载并返回变量的值。operator T是load的简化版,内部调用的是load(memory_order_seq_cst)形式。

(4)exchange:交换,赋值后返回变量赋值前的值。exchange也称为read-modify-write操作。

T exchange(T desr, memory_order m = memory_order_seq_cst) volatile noexcept;

T exchange(T desr, memory_order m = memory_order_seq_cst) noexcept;

(5)compare_exchange_weak:这就是有名的CAS(Compare And Swap: 比较并交换)。操作是原子的,排它的。其它线程如果想要读取或修改该原子对象时,会等待先该操作完成。

(6)compare_exchange_strong:

进行compare时,与weak版一样,都是比较的物理内容。与weak版不同的是,strong版本不会返回伪false。即:原子对象所封装的值如果与expect在物理内容上相同,strong版本一定会返回true。其所付出的代价是:在某些需要循环检测的算法,或某些平台下,其性能较compare_exchange_weak要差。但对于某些不需要采用循环检测的算法而言, 通常采用compare_exchange_strong 更好。

std::atomic特化

(1)fetch_add:该函数将原子对象封装的值加上v,同时返回原子对象的旧值。其功能用伪代码表示为:

// T is integral

T fetch_add(T v, memory_order m = memory_order_seq_cst) volatile noexcept;

T fetch_add(T v, memory_order m = memory_order_seq_cst) noexcept;

// T is pointer

T fetch_add(ptrdiff_t v, memory_order m = memory_order_seq_cst) volatile noexcept;

T fetch_add(ptrdiff_t v, memory_order m = memory_order_seq_cst) noexcept;

(2)fetch_sub:该函数将原子对象封装的值减去v,同时返回原子对象的旧值。其功能用伪代码表示为:

// T is integral

T fetch_sub(T v, memory_order m = memory_order_seq_cst) volatile noexcept;

T fetch_sub(T v, memory_order m = memory_order_seq_cst) noexcept;

// T is pointer

T fetch_sub(ptrdiff_t v, memory_order m = memory_order_seq_cst) volatile noexcept;

T fetch_sub(ptrdiff_t v, memory_order m = memory_order_seq_cst) noexcept;

(3)++, –, +=, -=:不管是基于整数的特化,还是指针特化,atomic均支持这四种操作。其用法与未封装时一样

独属于数值型特化的原子操作 – 位操作:

(1)fetch_and,fetch_or,fetch_xor:

位操作,将contained按指定方式进行位操作,并返回contained的旧值。

integral fetch_and(integral v, memory_order m = memory_order_seq_cst) volatile noexcept;

integral fetch_and(integral v, memory_order m = memory_order_seq_cst) noexcept;

integral fetch_or(integral v, memory_order m = memory_order_seq_cst) volatile noexcept;

integral fetch_or(integral v, memory_order m = memory_order_seq_cst) noexcept;

integral fetch_xor(integral v, memory_order m = memory_order_seq_cst) volatile noexcept;

integral fetch_xor(integral v, memory_order m = memory_order_seq_cst) noexcept;

(2)perator &=,operator |=,operator ^=:与相应的fetch_*操作不同的是,operator操作返回的是新值

T operator &=(T v) volatile noexcept {return fetch_and(v) & v;}

T operator &=(T v) noexcept {return fetch_and(v) & v;}

T operator |=(T v) volatile noexcept {return fetch_or(v) | v;}

T operator |=(T v) noexcept {return fetch_or(v) | v;}

T operator ^=(T v) volatile noexcept {return fetch_xor(v) ^ v;}

T operator ^=(T v) noexcept {return fetch_xor(v) ^ v;}

郑重声明:本文内容及图片均整理自互联网,不代表本站立场,版权归原作者所有,如有侵权请联系管理员(admin#wlmqw.com)删除。
(0)
用户投稿
上一篇 2022年6月30日
下一篇 2022年6月30日

相关推荐

联系我们

联系邮箱:admin#wlmqw.com
工作时间:周一至周五,10:30-18:30,节假日休息