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 01aafde

Browse files
committed
更新视频代码
1 parent 7877d0e commit 01aafde

File tree

6 files changed

+176
-2
lines changed

6 files changed

+176
-2
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include <iostream>
2+
#include <atomic>
3+
#include <mutex>
4+
#include <thread>
5+
6+
class spinlock_mutex {
7+
std::atomic_flag flag{};
8+
public:
9+
spinlock_mutex()noexcept = default;
10+
void lock()noexcept {
11+
while (flag.test_and_set(std::memory_order_acquire));
12+
}
13+
14+
void unlock()noexcept {
15+
flag.clear(std::memory_order_release);
16+
}
17+
};
18+
19+
spinlock_mutex m;
20+
21+
void f() {
22+
std::lock_guard<spinlock_mutex> lc{ m };
23+
std::cout << "😅😅" << "❤️❤️\n";
24+
}
25+
26+
int main(){
27+
std::thread t{ f };
28+
std::thread t1{ f };
29+
std::thread t2{ f };
30+
std::thread t3{ f };
31+
std::thread t4{ f };
32+
std::thread t5{ f };
33+
t.join();
34+
t1.join();
35+
t2.join();
36+
t3.join();
37+
t4.join();
38+
t5.join();
39+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#include <atomic>
2+
#include <iostream>
3+
#include <thread>
4+
5+
std::atomic<bool> flag{ false };
6+
bool expected = false;
7+
8+
void try_set_flag() {
9+
// 尝试将 flag 设置为 true,如果当前值为 false
10+
if (flag.compare_exchange_strong(expected, true)) {
11+
std::cout << "flag 为 false,flag 设为 true。\n";
12+
}
13+
else {
14+
std::cout << "flag 为 true, expected 设为 true。\n";
15+
}
16+
}
17+
18+
int main() {
19+
std::thread t1{ try_set_flag };
20+
std::thread t2{ try_set_flag };
21+
t1.join();
22+
t2.join();
23+
std::cout << "flag: " << std::boolalpha << flag << '\n';
24+
std::cout << "expected: " << std::boolalpha << expected << '\n';
25+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include <iostream>
2+
3+
struct X{
4+
int v{};
5+
void f()const {
6+
std::cout << v << '\n';
7+
}
8+
};
9+
10+
int main(){
11+
int arr[10]{ 1,2 };
12+
13+
std::atomic<int*> p{ arr };
14+
15+
p.fetch_add(1);
16+
std::cout << *(p.load()) << '\n';
17+
18+
p.fetch_sub(1);
19+
std::cout << *(p.load()) << '\n';
20+
21+
p += 1;
22+
std::cout << *(p.load()) << '\n';
23+
24+
p -= 1;
25+
std::cout << *(p.load()) << '\n';
26+
27+
X xs[3]{ {10},{20},{30} };
28+
std::atomic<X*> p2{ xs };
29+
p2.load()->f();
30+
p2 += 2;
31+
p2.load()->f();
32+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include <iostream>
2+
#include <memory>
3+
#include <thread>
4+
#include <chrono>
5+
#include <syncstream>
6+
using namespace std::chrono_literals;
7+
8+
class Data {
9+
public:
10+
Data(int value = 0) : value_(value) {}
11+
int get_value() const { return value_; }
12+
void set_value(int new_value) { value_ = new_value; }
13+
private:
14+
int value_;
15+
};
16+
17+
std::atomic<std::shared_ptr<Data>> data = std::make_shared<Data>();
18+
19+
void writer() {
20+
for (int i = 0; i < 10; ++i) {
21+
std::shared_ptr<Data> new_data = std::make_shared<Data>(i);
22+
data.store(new_data);
23+
std::this_thread::sleep_for(100ms);
24+
}
25+
}
26+
27+
void reader() {
28+
for (int i = 0; i < 10; ++i) {
29+
if (auto sp = data.load()) {
30+
std::cout << "读取线程值: " << sp->get_value() << std::endl;
31+
}
32+
else {
33+
std::cout << "没有读取到数据" << std::endl;
34+
}
35+
std::this_thread::sleep_for(100ms);
36+
}
37+
}
38+
39+
std::atomic<std::shared_ptr<int>> ptr = std::make_shared<int>();
40+
41+
void wait_for_wake_up() {
42+
std::osyncstream{ std::cout }
43+
<< "线程 "
44+
<< std::this_thread::get_id()
45+
<< " 阻塞,等待更新唤醒\n";
46+
47+
// 等待 ptr 变为其它值
48+
ptr.wait(ptr.load());
49+
50+
std::osyncstream{ std::cout }
51+
<< "线程 "
52+
<< std::this_thread::get_id()
53+
<< " 已被唤醒\n";
54+
}
55+
56+
void wake_up() {
57+
std::this_thread::sleep_for(5s);
58+
59+
// 更新值并唤醒
60+
ptr.store(std::make_shared<int>(10));
61+
ptr.notify_one();
62+
}
63+
64+
int main() {
65+
//std::thread writer_thread{ writer };
66+
//std::thread reader_thread{ reader };
67+
68+
//writer_thread.join();
69+
//reader_thread.join();
70+
71+
//std::atomic<std::shared_ptr<int>> ptr = std::make_shared<int>(10);
72+
//std::atomic_ref<int> ref{ *ptr.load() };
73+
//ref = 100; // 原子地赋 100 给被引用的对象
74+
//std::cout << *ptr.load() << '\n';
75+
std::thread t1{ wait_for_wake_up };
76+
wake_up();
77+
t1.join();
78+
}

‎code/ModernCpp-ConcurrentProgramming-Tutorial/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "C
1212
add_compile_options("-finput-charset=UTF-8" "-fexec-charset=UTF-8" "-fopenmp")
1313
endif()
1414

15-
add_executable(${PROJECT_NAME} "41实现一个线程池.cpp")
15+
add_executable(${PROJECT_NAME} "45原子特化shared_ptr.cpp")
1616

1717
set(SFML_DIR "D:/lib/SFML-2.6.1-windows-vc17-64-bit/SFML-2.6.1/lib/cmake/SFML")
1818
find_package(SFML 2.6.1 COMPONENTS system window graphics audio network REQUIRED)

‎md/05内存模型与原子操作.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ void f(){
311311
312312
稍微聊一下原理,我们的 `spinlock_mutex` 对象中存储的 `flag` 对象在默认构造时是清除 (`false`) 状态。在 `lock()` 函数中调用 `test_and_set` 函数,它是原子的,只有一个线程能成功调用并将 `flag` 的状态原子地更改为设置 (`true`),并返回它先前的值 (`false`)。此时,该线程成功获取了锁,退出循环。
313313

314-
`flag` 对象的状态为设置 (`true`) 时,其线程调用 `test_and_set` 函数会返回 `true`,导致它们继续在循环中自旋,无法退出。直到先前持有锁的线程调用 `unlock()` 函数,将 `flag` 对象的状态原子地更改为清除 (`false`) 状态。此时,等待的线程中会有一个线程成功调用 `test_and_set` 返回 `false`,然后退出循环,成功获取锁。
314+
`flag` 对象的状态为设置 (`true`) 时,其它线程调用 `test_and_set` 函数会返回 `true`,导致它们继续在循环中自旋,无法退出。直到先前持有锁的线程调用 `unlock()` 函数,将 `flag` 对象的状态原子地更改为清除 (`false`) 状态。此时,等待的线程中会有一个线程成功调用 `test_and_set` 返回 `false`,然后退出循环,成功获取锁。
315315

316316
> 值得注意的是,我们只是稍微的讲一下使用 `std::atomic_flag` 实现自旋锁。不过并不推荐各位在实践中使用它,具体可参见 [**Linus Torvalds**](https://en.wikipedia.org/wiki/Linus_Torvalds)[文章](https://www.realworldtech.com/forum/?threadid=189711&curpostid=189723)。其中有一段话说得很直接:
317317
>

0 commit comments

Comments
(0)

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