Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 79952e4

Browse files
committed
更新教案
1. 修改第二、第三章的部分微小措辞以及代码格式。 2. 更新项目文件中的代码示例,用作视频学习。
1 parent 4f43473 commit 79952e4

16 files changed

+436
-13
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
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+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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,优化,直接缓存这个值
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
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+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
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+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
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+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /