File tree 16 files changed +436
-13
lines changed
code/ModernCpp-ConcurrentProgramming-Tutorial
16 files changed +436
-13
lines changed Original file line number Diff line number Diff line change
1
+ #include < iostream>
2
+ #include < thread>
3
+ #include < type_traits>
4
+ #include < vector>
5
+ #include < mutex>
6
+
7
+ class joining_thread {
8
+ std::thread t;
9
+ public:
10
+ joining_thread ()noexcept = default ;
11
+
12
+ template <typename Callable, typename ... Args>
13
+ explicit joining_thread (Callable&& func, Args&&...args) :
14
+ t{ std::forward<Callable>(func), std::forward<Args>(args)... } {}
15
+
16
+ explicit joining_thread (std::thread t_)noexcept : t{ std::move (t_) } {}
17
+
18
+ joining_thread (joining_thread&& other)noexcept : t{ std::move (other.t ) } {}
19
+
20
+ joining_thread& operator =(std::thread&& other)noexcept {
21
+ if (joinable ()) { // 如果当前有活跃线程(判断当前对象是否持有资源),那就先执行完(先释放)
22
+ join (); // 就相当于释放资源一样的意思
23
+ }
24
+ t = std::move (other);
25
+ return *this ;
26
+ }
27
+ ~joining_thread () {
28
+ if (joinable ()) {
29
+ join ();
30
+ }
31
+ }
32
+ void swap (joining_thread& other)noexcept {
33
+ t.swap (other.t );
34
+ }
35
+ std::thread::id get_id ()const noexcept {
36
+ return t.get_id ();
37
+ }
38
+ bool joinable ()const noexcept {
39
+ return t.joinable ();
40
+ }
41
+ void join () {
42
+ t.join ();
43
+ }
44
+ void detach () {
45
+ t.detach ();
46
+ }
47
+ std::thread& data ()noexcept {
48
+ return t;
49
+ }
50
+ const std::thread& data ()const noexcept {
51
+ return t;
52
+ }
53
+ };
54
+
55
+ int main (){
56
+ auto func = []{
57
+ std::cout << std::this_thread::get_id () << ' \n ' ;
58
+ };
59
+
60
+ std::vector<std::thread> vec;
61
+
62
+ for (int i = 0 ; i < 10 ; ++i){
63
+ vec.emplace_back (func);
64
+ }
65
+
66
+ for (auto & thread : vec){
67
+ thread.join ();
68
+ }
69
+ }
Original file line number Diff line number Diff line change
1
+ #include < iostream>
2
+ #include < thread>
3
+
4
+ using namespace std ::literals::chrono_literals;
5
+
6
+ void f (std::stop_token stop_token, int value) {
7
+ while (!stop_token.stop_requested ()) { // 检查是否已经收到停止请求
8
+ std::cout << value++ << ' ' << std::flush;
9
+ std::this_thread::sleep_for (200ms);
10
+ }
11
+ std::cout << std::endl;
12
+ }
13
+
14
+ int main () {
15
+ std::jthread thread{ f, 1 }; // 打印 1..15 大约 3 秒
16
+ std::this_thread::sleep_for (3s);
17
+ thread.request_stop (); // 发送信息,线程终止
18
+ std::cout << " 乐\n " ;
19
+ // jthread 的析构函数调用 request_stop() 和 join()。
20
+ }
Original file line number Diff line number Diff line change
1
+ #include < iostream>
2
+ #include < thread>
3
+ #include < vector>
4
+
5
+ std::vector<int > v;
6
+
7
+ int n = 1 ;
8
+
9
+ int main () {
10
+ int cnt = 0 ;
11
+ auto f = [&] { cnt++; };
12
+ std::thread t1{ f }, t2{ f }, t3{ f }; // ub 未定义行为
13
+ t1.join ();
14
+ t2.join ();
15
+ t3.join ();
16
+ std::cout << cnt << ' \n ' ;
17
+ }
18
+ // 数据竞争它是未定义行为,但是 C++ 的编译器,它会假设你的程序(假设程序是对的,代码是对的)没有任何的未定义行为再去进行优化
19
+ // 输出 n,优化,直接缓存这个值
Original file line number Diff line number Diff line change
1
+ #include < iostream>
2
+ #include < thread>
3
+ #include < vector>
4
+ #include < mutex>
5
+ #include < algorithm>
6
+ #include < list>
7
+ #include < numeric>
8
+
9
+ std::mutex m;
10
+
11
+ // 写
12
+ void add_to_list (int n, std::list<int >& list) {
13
+ std::vector<int > numbers (n + 1 );
14
+ std::iota (numbers.begin (), numbers.end (), 0 );
15
+ int sum = std::accumulate (numbers.begin (), numbers.end (), 0 );
16
+
17
+ {
18
+ std::scoped_lock lc{ m };
19
+ list.push_back (sum);
20
+ }
21
+ }
22
+
23
+ // 读
24
+ void print_list (const std::list<int >& list) {
25
+ std::scoped_lock lc{ m };
26
+ for (const auto & i : list) {
27
+ std::cout << i << ' ' ;
28
+ }
29
+ std::cout << ' \n ' ;
30
+ }
31
+
32
+ int main (){
33
+ std::list<int > list;
34
+ std::thread t1{ add_to_list,10 ,std::ref (list) };
35
+ std::thread t2{ add_to_list,10 ,std::ref (list) };
36
+ std::thread t3{ print_list,std::cref (list) };
37
+ std::thread t4{ print_list,std::cref (list) };
38
+ t1.join ();
39
+ t2.join ();
40
+ t3.join ();
41
+ t4.join ();
42
+ std::cout << " ---------------------\n " ;
43
+ print_list (list);
44
+ }
Original file line number Diff line number Diff line change
1
+ #include < iostream>
2
+ #include < thread>
3
+ #include < vector>
4
+ #include < mutex>
5
+ #include < string>
6
+ using namespace std ::string_literals;
7
+
8
+ std::mutex mtx;
9
+
10
+ void thread_function (int id) {
11
+ // 尝试加锁
12
+ if (mtx.try_lock ()) {
13
+ std::string s = " 线程:" s + std::to_string (id) + " 获得锁" s + " \n " ;
14
+ std::string s2 = " 线程:" s + std::to_string (id) + " 释放锁" s + " \n " ;
15
+ std::cout << s;
16
+ // 临界区代码
17
+ std::this_thread::sleep_for (std::chrono::milliseconds (100 )); // 模拟临界区操作
18
+ mtx.unlock (); // 解锁
19
+ std::cout << s2;
20
+ }
21
+ else {
22
+ std::string s = " 线程:" s + std::to_string (id) + " 获取锁失败 处理步骤" s + " \n " ;
23
+ std::cout << s;
24
+ }
25
+ }
26
+
27
+ int main (){
28
+ std::thread t1 (thread_function, 1 );
29
+ std::thread t2 (thread_function, 2 );
30
+
31
+ t1.join ();
32
+ t2.join ();
33
+ }
Original file line number Diff line number Diff line change
1
+ #include < iostream>
2
+ #include < thread>
3
+ #include < mutex>
4
+
5
+ class Data {
6
+ int a{};
7
+ std::string b{};
8
+ public:
9
+ void do_something () {
10
+ // 修改数据成员等...
11
+ }
12
+ };
13
+
14
+ class Data_wrapper {
15
+ Data data;
16
+ std::mutex m;
17
+ public:
18
+ template <class Func >
19
+ void process_data (Func func) {
20
+ std::lock_guard<std::mutex> lc{ m };
21
+ func (data); // 受保护数据传递给函数
22
+ }
23
+ };
24
+
25
+ Data* p = nullptr ;
26
+
27
+ void malicious_function (Data& protected_data) {
28
+ p = &protected_data; // 受保护的数据被传递到外部
29
+ }
30
+
31
+ Data_wrapper d;
32
+
33
+ void foo () {
34
+ d.process_data (malicious_function); // 传递了一个恶意的函数
35
+ p->do_something (); // 在无保护的情况下访问保护数据
36
+ }
37
+
38
+ int main (){
39
+
40
+ }
Original file line number Diff line number Diff line change
1
+ #include < iostream>
2
+ #include < thread>
3
+ #include < mutex>
4
+ #include < chrono>
5
+ using namespace std ::chrono_literals;
6
+
7
+ struct X {
8
+ X (const std::string& str) :object{ str } {}
9
+
10
+ friend void swap (X& lhs, X& rhs);
11
+ private:
12
+ std::string object;
13
+ std::mutex m;
14
+ };
15
+
16
+ void swap (X& lhs, X& rhs) {
17
+ if (&lhs == &rhs) return ;
18
+ std::scoped_lock guard{ lhs.m ,rhs.m };
19
+ swap (lhs.object , rhs.object );
20
+ }
21
+
22
+ int main (){
23
+ X a{ " 🤣" }, b{ " 😅" };
24
+ std::thread t{ [&] {swap (a, b); } }; // 1
25
+ std::thread t2{ [&] {swap (b, a); } }; // 2
26
+ t.join ();
27
+ t2.join ();
28
+ }
Original file line number Diff line number Diff line change
1
+ #include < iostream>
2
+ #include < thread>
3
+ #include < mutex>
4
+ #include < chrono>
5
+ using namespace std ::chrono_literals;
6
+
7
+ struct X {
8
+ X (const std::string& str) :object{ str } {}
9
+
10
+ friend void swap (X& lhs, X& rhs);
11
+ private:
12
+ std::string object;
13
+ std::mutex m;
14
+ };
15
+
16
+ void swap (X& lhs, X& rhs) {
17
+ if (&lhs == &rhs) return ;
18
+ std::lock (rhs.m , lhs.m );
19
+
20
+ std::unique_lock<std::mutex> lock1{ lhs.m , std::adopt_lock };
21
+ std::unique_lock<std::mutex> lock2{ rhs.m , std::adopt_lock };
22
+ // std::lock(lock1, lock2);
23
+ swap (lhs.object , rhs.object );
24
+ }
25
+
26
+ int main () {
27
+ X a{ " 🤣" }, b{ " 😅" };
28
+ std::thread t{ [&] {swap (a, b); } }; // 1
29
+ std::thread t2{ [&] {swap (b, a); } }; // 2
30
+ t.join ();
31
+ t2.join ();
32
+ }
Original file line number Diff line number Diff line change
1
+ #include < iostream>
2
+ #include < thread>
3
+ #include < mutex>
4
+ #include < chrono>
5
+ #include < memory>
6
+
7
+ std::unique_lock<std::mutex> get_lock () {
8
+ extern std::mutex some_mutex;
9
+ std::unique_lock<std::mutex> lk{ some_mutex };
10
+ return lk; // 选择到 unique_lock 的移动构造,转移所有权
11
+ }
12
+ void process_data () {
13
+ std::unique_lock<std::mutex> lk{ get_lock () }; // 转移到了主函数的 lk 中
14
+ // 执行一些任务...
15
+ }// 最后才会 unlock 解锁
16
+
17
+ int main (){
18
+ process_data ();
19
+ }
Original file line number Diff line number Diff line change
1
+ #include < iostream>
2
+ #include < thread>
3
+ #include < mutex>
4
+ #include < chrono>
5
+ #include < memory>
6
+
7
+ struct some {
8
+ void do_something (){}
9
+ };
10
+
11
+ std::shared_ptr<some> ptr;
12
+ std::once_flag resource_flag;
13
+
14
+ void init_resource () {
15
+ ptr.reset (new some);
16
+ }
17
+
18
+ void foo () {
19
+ std::call_once (resource_flag, []{ptr.reset (new some); }); // 线程安全的一次初始化
20
+ ptr->do_something ();
21
+ }
22
+
23
+ void test (){
24
+ std::call_once (resource_flag, [] {std::cout << " f init\n " ; });
25
+ }
26
+
27
+ std::once_flag flag;
28
+ int n = 0 ;
29
+
30
+ void f () {
31
+ std::call_once (flag, [] {
32
+ ++n;
33
+ std::cout << " 第 " << n << " 次调用\n " ;
34
+ throw std::runtime_error (" 异常" );
35
+ });
36
+ }
37
+
38
+ class my_class {};
39
+
40
+ inline my_class& get_my_class_instance () {
41
+ static my_class instance; // 线程安全的初始化过程 初始化严格发生一次
42
+ return instance;
43
+ }
44
+
45
+ int main () {
46
+ get_my_class_instance ();
47
+ get_my_class_instance ();
48
+ get_my_class_instance ();
49
+ get_my_class_instance ();
50
+ get_my_class_instance ();
51
+ }
You can’t perform that action at this time.
0 commit comments