File tree Expand file tree Collapse file tree 16 files changed +436
-13
lines changed
code/ModernCpp-ConcurrentProgramming-Tutorial Expand file tree Collapse file tree 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