Skip to content

Commit 7515d9b

Browse files
author
learnmoreonce
committed
ch5
1 parent 726b7cf commit 7515d9b

13 files changed

Lines changed: 89 additions & 42 deletions

Cpp-Concurrency-in-Action/CMakeLists.txt

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,18 @@ cmake_minimum_required(VERSION 3.6)
22

33

44
project(Cpp_Concurrency_in_Action)
5+
56
SET (CMAKE_C_COMPILER "/usr/bin/clang")
67
SET(CMAKE_CXX_COMPILER "clang++")
8+
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -lpthread ")
9+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -lpthread -stdlib=libc++ -lc++abi ")
10+
711
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++ -std=c++14 -lc++abi -lboost_thread -lboost_system ")
8-
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++1z -lpthread -stdlib=libc++ -lc++abi ")
12+
13+
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -lpthread ")
14+
915
add_subdirectory(ch1)
1016
add_subdirectory(ch2)
1117
add_subdirectory(ch3)
12-
add_subdirectory(ch4)
18+
add_subdirectory(ch4)
19+
add_subdirectory(ch5)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
2+
add_executable(listing_5.0.3_atomic_default listing_5.0.3_atomic_default.cpp)
3+
add_executable(listing_5.0.4_atomic_flag_test_and_set listing_5.0.4_atomic_flag_test_and_set.cpp)
4+
5+
add_executable(listing_5.1.1 listing_5.1.1.cpp)
6+
add_executable(listing_5.1.2 listing_5.1.2.cpp)
7+
add_executable(listing_5.1.3 listing_5.1.3.cpp)

Cpp-Concurrency-in-Action/ch5/listing_5.0.0std_atomic.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11

2+
#include <atomic>
23
/*
34
原子类型对象的主要特点就是从不同线程访问不会导致数据竞争(data race)。
45
因此从不同线程访问某个原子对象是良性 (well-defined) 行为,

Cpp-Concurrency-in-Action/ch5/listing_5.0.1integal_整数特化.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
//
2-
// Created by shen on 16-11-6.
3-
//
4-
/*
5-
* 另外,C++11 标准库 std::atomic 提供了针对整形(integral)和指针类型的特化实现,分别定义如下:
61

2+
/*
3+
另外,C++11 标准库 std::atomic 提供了针对整形(integral)和指针类型的特化实现,分别定义如下:
74
针对整形(integal)的特化,其中 integal 代表了如下类型
8-
char, signed char, unsigned char, short, unsigned short, int, unsigned int,
9-
long, unsigned long, long long, unsigned long long, char16_t, char32_t, wchar_t:
5+
char, signed char, unsigned char, short, unsigned short, int, unsigned int,
6+
long, unsigned long, long long, unsigned long long, char16_t, char32_t, wchar_t:
107
*/
118
template <> struct atomic<integral> {
129
bool is_lock_free() const volatile;

Cpp-Concurrency-in-Action/ch5/listing_5.0.2_atomic指针特化.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
//
2-
// Created by shen on 16-11-6.
3-
//
1+
42
template <class T> struct atomic<T*> {
53
bool is_lock_free() const volatile;
64
bool is_lock_free() const;

Cpp-Concurrency-in-Action/ch5/listing_5.0.3_atomic_default.cpp

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
//
2-
// Created by shen on 16-11-6.
3-
//
4-
5-
include <iostream> // std::cout
1+
#include <iostream> // std::cout
62
#include <atomic> // std::atomic, std::atomic_flag, ATOMIC_FLAG_INIT
73
#include <thread> // std::thread, std::this_thread::yield
84
#include <vector> // std::vector
@@ -13,9 +9,9 @@ std::atomic_flag winner = ATOMIC_FLAG_INIT;
139

1410
void do_count1m(int id)
1511
{
16-
while (!ready) { std::this_thread::yield(); } // 等待 ready 变为 true.
12+
while (!ready) { std::this_thread::yield(); } //礼让线程,等待ready变为true.
1713

18-
for (volatile int i=0; i<1000000; ++i) {} // 计数
14+
for (volatile int i=0; i<100000000; ++i) {} // 计数
1915

2016
if (!winner.test_and_set()) {
2117
std::cout << "thread #" << id << " won!\n";
@@ -26,7 +22,7 @@ int main ()
2622
{
2723
std::vector<std::thread> threads;
2824
std::cout << "spawning 10 threads that count to 1 million...\n";
29-
for (int i=1; i<=10; ++i) threads.push_back(std::thread(count1m,i));
25+
for (int i=1; i<=10; ++i) threads.push_back(std::thread(do_count1m,i));
3026
ready = true;
3127

3228
for (auto& th : threads) th.join();
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// atomic_flag as a spinning lock
2+
#include <iostream> // std::cout
3+
#include <atomic> // std::atomic_flag
4+
#include <thread> // std::thread
5+
#include <vector> // std::vector
6+
#include <sstream> // std::stringstream
7+
8+
/*
9+
bool test_and_set (memory_order sync = memory_order_seq_cst) noexcept;
10+
11+
Sets the atomic_flag and returns whether it was already set immediately before the call.
12+
13+
The entire operation is atomic (an atomic read-modify-write operation):
14+
the value is not affected by other threads between the instant its value
15+
is read (to be returned) and the moment it is modified by this function.
16+
17+
true if the flag was set before the call.
18+
false otherwise.
19+
*/
20+
21+
std::atomic_flag lock_stream = ATOMIC_FLAG_INIT;
22+
std::stringstream stream;
23+
24+
void append_number(int x) {
25+
while (lock_stream.test_and_set()) {}
26+
stream << "thread #" << x << '\n';
27+
lock_stream.clear();
28+
}
29+
30+
int main ()
31+
{
32+
std::vector<std::thread> threads;
33+
for (int i=1; i<=10; ++i) threads.push_back(std::thread(append_number,i));
34+
for (auto& th : threads) th.join();
35+
36+
std::cout << stream.str();
37+
return 0;
38+
}

Cpp-Concurrency-in-Action/ch5/listing_5.1.1.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
//
2-
// Created by shen on 16-11-6.
3-
//
41

52
#include <iostream> // std::cout
63
#include <atomic> // std::atomic, std::atomic_flag, ATOMIC_FLAG_INIT
@@ -22,15 +19,21 @@ void count1m(int id)
2219
// 如果某个线程率先执行完上面的计数过程,则输出自己的 ID.
2320
// 此后其他线程执行 test_and_set 是 if 语句判断为 false,
2421
// 因此不会输出自身 ID.
25-
if (!winner.test_and_set()) {
22+
if (!winner.test_and_set()) {//之前未被设置,返回true。
2623
std::cout << "thread #" << id << " won!\n";
2724
}
2825
};
2926

3027
/*
31-
test_and_set() 函数检查 std::atomic_flag 标志,如果 std::atomic_flag 之前没有被设置过,
32-
则设置 std::atomic_flag 的标志,并返回先前该 std::atomic_flag 对象是否被设置过,如果之前
33-
std::atomic_flag 对象已被设置,则返回 true,否则返回 false。
28+
test_and_set() 函数检查 std::atomic_flag 标志
29+
(一):
30+
1),如果 std::atomic_flag 之前没有被设置过,
31+
2),则设置 std::atomic_flag 的标志,并返回先前该 std::atomic_flag 对象是否被设置过.
32+
33+
(二):
34+
1),如果之前std::atomic_flag 对象已被设置,则返回 true
35+
2),否则返回 false。
36+
3437
test-and-set 操作是原子的(因此 test-and-set 是原子 read-modify-write (RMW)操作)
3538
*/
3639

Cpp-Concurrency-in-Action/ch5/listing_5.1.2.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
//
2-
// Created by shen on 16-11-6.
3-
//
41

52
#include <iostream> // std::cout
63
#include <atomic> // std::atomic_flag

Cpp-Concurrency-in-Action/ch5/listing_5.1.3.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
//
2-
// Created by shen on 16-11-6.
3-
//
41

52
#include <thread>
63
#include <vector>
@@ -30,9 +27,9 @@ int main()
3027
}
3128
}
3229

33-
/*http://www.cnblogs.com/haippy/p/3252056.html
30+
/*
3431
在上面的程序中,std::atomic_flag 对象 lock 的上锁操作可以理解为 lock.test_and_set(std::memory_order_acquire);
35-
(此处指定了 Memory Order,更多有关 Memory Order 的概念,我会在后续的文章中介绍),
32+
(此处指定了 Memory Order,更多有关 Memory Order 的概念 )
3633
解锁操作相当与 lock.clear(std::memory_order_release)。
3734
在上锁的时候,如果 lock.test_and_set 返回 false,则表示上锁成功(此时 while 不会进入自旋状态),
3835
因为此前 lock 的标志位为 false(即没有线程对 lock 进行上锁操作),但调用 test_and_set 后 lock 的标志位为 true,

0 commit comments

Comments
 (0)