﻿ C++11中的原子量和内存序详解 - 鸿网互联

# C++11中的原子量和内存序详解

(a) i++问题

step operation 1 i->reg(读取i的值到寄存器) 2 inc-reg(在寄存器中自增i的值) 3 reg->i (写回内存中的i)

step thread A thread B 1 i->reg 2 inc-reg 3 i->reg 4 inc-reg 5 reg->i 6 reg->i

(b)指令重排问题

step thread A thread B 1 a = 1 2 flag= true 3 if flag== true 4 assert(a == 1)

step thread A thread B 1 flag = true 2 if flag== true 3 assert(a == 1) 4 a = 1

C++11标准在标准库atomic头文件提供了模版atomic<>来定义原子量：

```template< class T >
struct atomic;```

```std::atomic_bool std::atomic<bool>
std::atomic_char std::atomic<char>
std::atomic_schar std::atomic<signed char>
std::atomic_uchar std::atomic<unsigned char>
std::atomic_short std::atomic<short>
std::atomic_ushort std::atomic<unsigned short>
std::atomic_int std::atomic<int>
std::atomic_uint std::atomic<unsigned int>
std::atomic_long std::atomic<long>
······
//更多类型见：http://en.cppreference.com/w/cpp/atomic/atomic```

`std::atomic<int> i;`

```#include <iostream>
#include <atomic>
#include <vector>
#include <functional>

std::atomic<int> i;
const int count = 100000;
const int n = 10;

{
for (int j = 0; j < count; ++j)
i++;
}

int main()
{
i.store(0);
std::cout << "start " << n << " workers, "
<< "every woker inc " << count << " times" << std::endl;

for (int j = 0; j < n; ++j)

for (auto & w : workers)
w.join();

std::cout << "workers end "
<< "finally i is " << i << std::endl;

if (i == n * count)
std::cout << "i++ test passed!" << std::endl;
else
std::cout << "i++ test failed!" << std::endl;

return 0;
}```

```start 10 workers, every woker inc 100000 times
workers end finally i is 1000000
i++ test passed!```

```start 10 workers, every woker inc 100000 times
workers end finally i is 445227
i++ test failed!```

http://en.cppreference.com/w/cpp/concept/TriviallyCopyable

```class {
int x;
int y;
}```

```class {
int x;
int y;
{
return x + y;
}
}```

```#include <iostream>
#include <atomic>

#define N 8

struct A {
char a[N];
};

int main()
{
std::atomic<A> a;
std::cout << sizeof(A) << std::endl;
std::cout << a.is_lock_free() << std::endl;
return 0;
}```

8
1

N sizeof(A) is_lock_free() 1 1 1 2 2 1 3 3 0 4 4 1 5 5 0 6 6 0 7 7 0 8 8 1 > 8 / 0

type sizeof() is_lock_free() char 1 1 short 2 1 int 4 1 long long 8 1 float 4 1 double 8 1

```bool __atomic_compare_exchange_n (type *ptr, type *expected, type desired, bool weak, int success_memorder, int failure_memorder)

bool __atomic_compare_exchange (type *ptr, type *expected, type *desired, bool weak, int success_memorder, int failure_memorder)```

The ‘__atomic' builtins can be used with any integral scalar or pointer type that is 1, 2, 4, or 8 bytes in length. 16-byte integral types are also allowed if ‘__int128' (see __int128) is supported by the architecture.

type类型的长度应该为1、2、4、8字节中的一个，少数支持__int128的平台可以到16字节，所以只有长度为1，2，4，8字节的数据才能实现无锁。这个只是我的推测，具体是否如此尚不明白。

void store( T desired, std::memory_order order = std::memory_order_seq_cst )

```typedef enum memory_order {
memory_order_relaxed,
memory_order_consume,
memory_order_acquire,
memory_order_release,
memory_order_acq_rel,
memory_order_seq_cst
} memory_order;```

memory_order_release/memory_order_acquire

step thread A thread B 1 a = 1 2 flag.store(true, memory_order_release) 3 if( true == flag.load(memory_order_acquire)) 4 assert(a == 1)

memory_order_release/memory_order_consume

• 对于同一个原子变量，release操作所依赖的写入，一定对随后consume操作后依赖于该原子变量的操作可见。

step thread A thread B 1 b = true 2 a = 1 3 flag.store(b, memory_order_release) 4 while (!(c = flag.load(memory_order_consume))) 5 assert(a == 1) 6 assert(c == true) 7 assert(b == true)

step4使得c依赖于flag，当step4线程B读取到flag的值为true的时候，由于flag依赖于b，b在之前的写入是可见的，此时b一定为true，所以step6、step7的断言一定会成功。而且这种依赖关系具有传递性，假如b又依赖与另一个变量d，则d在之前的写入同样对step4之后的操作可见。那么a呢？很遗憾在这种内存序下a并不能得到保证，step5的断言可能会失败。

memory_order_acq_rel

step thread A thread B 1 a = 1 2 flag.store(true, memory_order_release) 3 b = true 4 c = 2 5 while (!flag.compare_exchange_weak(b, false, memory_order_acq_rel)) {b = true} 6 assert(a == 1) 7 if (true == flag.load(memory_order_acquire) 8 assert(c == 2)

memory_order_seq_cst

memory_order_relaxed

<
{"ft_lang_label":"__label__zh","ft_lang_prob":0.85011387,"math_prob":0.88186705,"size":7951,"snap":"2022-40-2023-06","text_gpt3_token_len":4963,"char_repetition_ratio":0.13439034,"word_repetition_ratio":0.09170306,"special_character_ratio":0.200981,"punctuation_ratio":0.17349137,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.97092867,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2023-02-08T06:43:14Z\",\"WARC-Record-ID\":\"<urn:uuid:986d8cd9-dedb-4fd3-bc8f-cb5b0d23a828>\",\"Content-Length\":\"35536\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:fe29d4ec-715b-4209-9558-5baa615c3f0a>\",\"WARC-Concurrent-To\":\"<urn:uuid:273ba9c4-1b05-4934-ac1d-867277291828>\",\"WARC-IP-Address\":\"183.60.108.128\",\"WARC-Target-URI\":\"https://news.68idc.cn/buildlang/cyuyan/20210923713596.html\",\"WARC-Payload-Digest\":\"sha1:XKCEUFXGJRPYFXLLVE7YNN5XQ7QAGNSP\",\"WARC-Block-Digest\":\"sha1:DIUGRPDKRIE3Y5UCOKFCXHYWLRVXCLJV\",\"WARC-Identified-Payload-Type\":\"application/xhtml+xml\",\"warc_filename\":\"/cc_download/warc_2023/CC-MAIN-2023-06/CC-MAIN-2023-06_segments_1674764500719.31_warc_CC-MAIN-20230208060523-20230208090523-00277.warc.gz\"}"}