Skip to content

Commit 3367e2d

Browse files
committed
修改代码格式及其测试链接,确保类型与对象名字之间存在空格
1 parent 0b5fde6 commit 3367e2d

File tree

2 files changed

+30
-30
lines changed

2 files changed

+30
-30
lines changed

code/03共享数据/保护不常更新的数据结构.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class Settings {
1717
}
1818

1919
std::string get(const std::string& key) const {
20-
std::shared_lock<std::shared_mutex> lock(mutex_);
20+
std::shared_lock<std::shared_mutex> lock{ mutex_ };
2121
const auto it = data_.find(key);
2222
return (it != data_.end()) ? it->second : ""; // 如果没有找到键返回空字符串
2323
}

md/03共享数据.md

+29-29
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ void f() {
9191
}
9292
9393
int main() {
94-
std::vector<std::thread>threads;
94+
std::vector<std::thread> threads;
9595
for (std::size_t i = 0; i < 10; ++i)
9696
threads.emplace_back(f);
9797
@@ -100,7 +100,7 @@ int main() {
100100
}
101101
```
102102

103-
这段代码你多次[运行](https://godbolt.org/z/K7hcYxec9)它会得到毫无规律和格式的结果,我们可以使用[互斥量](https://zh.cppreference.com/w/cpp/thread/mutex)解决这个问题:
103+
这段代码你多次[运行](https://godbolt.org/z/93vTzcPzK)它会得到毫无规律和格式的结果,我们可以使用[互斥量](https://zh.cppreference.com/w/cpp/thread/mutex)解决这个问题:
104104

105105
```cpp
106106
#include <mutex> // 必要标头
@@ -182,7 +182,7 @@ private:
182182
void f(){
183183
//code..
184184
{
185-
std::lock_guard<std::mutex>lc{ m };
185+
std::lock_guard<std::mutex> lc{ m };
186186
// 涉及共享资源的修改的代码...
187187
}
188188
//code..
@@ -206,12 +206,12 @@ void add_to_list(int n, std::list<int>& list) {
206206
int sum = std::accumulate(numbers.begin(), numbers.end(), 0);
207207

208208
{
209-
std::lock_guard<std::mutex>lc{ m };
209+
std::lock_guard<std::mutex> lc{ m };
210210
list.push_back(sum);
211211
}
212212
}
213213
void print_list(const std::list<int>& list){
214-
std::lock_guard<std::mutex>lc{ m };
214+
std::lock_guard<std::mutex> lc{ m };
215215
for(const auto& i : list){
216216
std::cout << i << ' ';
217217
}
@@ -231,7 +231,7 @@ t3.join();
231231
t4.join();
232232
```
233233

234-
> 完整[代码测试](https://godbolt.org/z/ETeEsKhzK)
234+
> 完整[代码测试](https://godbolt.org/z/E3396dMxG)
235235
236236
先看 `add_to_list`,只有 `list.push_back(sum)` 涉及到了对共享数据的修改,需要进行保护,我们用 `{}` 包起来了。
237237

@@ -326,7 +326,7 @@ class Data_wrapper{
326326
public:
327327
template<class Func>
328328
void process_data(Func func){
329-
std::lock_guard<std::mutex>lc{m};
329+
std::lock_guard<std::mutex> lc{m};
330330
func(data); // 受保护数据传递给函数
331331
}
332332
};
@@ -368,20 +368,20 @@ std::mutex m1,m2;
368368
std::size_t n{};
369369
370370
void f(){
371-
std::lock_guard<std::mutex>lc1{ m1 };
372-
std::lock_guard<std::mutex>lc2{ m2 };;
371+
std::lock_guard<std::mutex> lc1{ m1 };
372+
std::lock_guard<std::mutex> lc2{ m2 };;
373373
++n;
374374
}
375375
void f2() {
376-
std::lock_guard<std::mutex>lc1{ m2 };
377-
std::lock_guard<std::mutex>lc2{ m1 };
376+
std::lock_guard<std::mutex> lc1{ m2 };
377+
std::lock_guard<std::mutex> lc2{ m1 };
378378
++n;
379379
}
380380
```
381381

382382
`f``f2` 因为互斥量**上锁顺序不同**,就有死锁风险。函数 `f` 先锁定 `m1`,然后再尝试锁定 `m2`,而函数 `f2` 先锁定 `m2` 再锁定 `m1` 。如果两个线程同时运行,它们就可能会彼此等待对方释放其所需的锁,从而造成死锁。
383383

384-
> 简而言之,有可能函数 f 锁定了 m1,函数 f2 锁定了 m2,函数 f 要往下执行,给 m2 上锁,所以在等待 f2 解锁 m2,然而函数 f2 也在等待函数 f 解锁 m1 它才能往下执行。所以死锁。[测试代码](https://godbolt.org/z/b9zYs44of)
384+
> 简而言之,有可能函数 f 锁定了 m1,函数 f2 锁定了 m2,函数 f 要往下执行,给 m2 上锁,所以在等待 f2 解锁 m2,然而函数 f2 也在等待函数 f 解锁 m1 它才能往下执行。所以死锁。[测试代码](https://godbolt.org/z/T8vWYzqnT)
385385
386386
---
387387

@@ -399,8 +399,8 @@ private:
399399

400400
void swap(X& lhs, X& rhs) {
401401
if (&lhs == &rhs) return;
402-
std::lock_guard<std::mutex>lock1{ lhs.m };
403-
std::lock_guard<std::mutex>lock2{ rhs.m };
402+
std::lock_guard<std::mutex> lock1{ lhs.m };
403+
std::lock_guard<std::mutex> lock2{ rhs.m };
404404
swap(lhs.object, rhs.object);
405405
}
406406
```
@@ -417,7 +417,7 @@ std::thread t2{ [&] {swap(b, a); } }; // 2
417417

418418
`2` 执行的时候,先上锁 b 的互斥量,再上锁 a 的互斥量。
419419

420-
> 完全可能线程 A 执行 1 的时候上锁了 a 的互斥量,线程 B 执行 `2` 上锁了 b 的互斥量。线程 A 往下执行需要上锁 b 的互斥量,线程 B 则要上锁 a 的互斥量执行完毕才能解锁,哪个都没办法往下执行,**死锁**[测试代码](https://godbolt.org/z/eYbjqEx54)
420+
> 完全可能线程 A 执行 1 的时候上锁了 a 的互斥量,线程 B 执行 `2` 上锁了 b 的互斥量。线程 A 往下执行需要上锁 b 的互斥量,线程 B 则要上锁 a 的互斥量执行完毕才能解锁,哪个都没办法往下执行,**死锁**[测试代码](https://godbolt.org/z/M6hfeb778)
421421
422422
其实也就是回到了第一个示例的问题。
423423

@@ -427,8 +427,8 @@ C++ 标准库有很多办法解决这个问题,**可以使用 [`std::lock`](ht
427427
void swap(X& lhs, X& rhs) {
428428
if (&lhs == &rhs) return;
429429
std::lock(lhs.m, rhs.m); // 给两个互斥量上锁
430-
std::lock_guard<std::mutex>lock1{ lhs.m,std::adopt_lock };
431-
std::lock_guard<std::mutex>lock2{ rhs.m,std::adopt_lock };
430+
std::lock_guard<std::mutex> lock1{ lhs.m,std::adopt_lock };
431+
std::lock_guard<std::mutex> lock2{ rhs.m,std::adopt_lock };
432432
swap(lhs.object, rhs.object);
433433
}
434434
```
@@ -476,8 +476,8 @@ void swap(X& lhs, X& rhs) {
476476
```cpp
477477
void swap(X& lhs, X& rhs) {
478478
if (&lhs == &rhs) return;
479-
std::unique_lock<std::mutex>lock1{ lhs.m, std::defer_lock };
480-
std::unique_lock<std::mutex>lock2{ rhs.m, std::defer_lock };
479+
std::unique_lock<std::mutex> lock1{ lhs.m, std::defer_lock };
480+
std::unique_lock<std::mutex> lock2{ rhs.m, std::defer_lock };
481481
std::lock(lock1, lock2);
482482
swap(lhs.object, rhs.object);
483483
++n;
@@ -563,7 +563,7 @@ std::mutex m;
563563

564564
int main() {
565565
m.lock();
566-
std::unique_lock<std::mutex>lock{ m,std::adopt_lock };
566+
std::unique_lock<std::mutex>lock { m,std::adopt_lock };
567567
}
568568
```
569569

@@ -583,7 +583,7 @@ int main() {
583583
void f() {
584584
//code..
585585

586-
std::unique_lock<std::mutex>lock{ m };
586+
std::unique_lock<std::mutex> lock{ m };
587587

588588
// 涉及共享资源的修改的代码...
589589

@@ -621,12 +621,12 @@ void f() {
621621
```cpp
622622
std::unique_lock<std::mutex>get_lock(){
623623
extern std::mutex some_mutex;
624-
std::unique_lock<std::mutex>lk{ some_mutex };
624+
std::unique_lock<std::mutex> lk{ some_mutex };
625625
return lk;
626626
627627
}
628628
void process_data(){
629-
std::unique_lock<std::mutex>lk{ get_lock() };
629+
std::unique_lock<std::mutex> lk{ get_lock() };
630630
// 执行一些任务...
631631
}
632632
```
@@ -639,7 +639,7 @@ void process_data(){
639639
640640
如果你简单写一个 `std::mutex some_mutex` 那么函数 `process_data` 中的 `lk` 会持有一个悬垂指针。
641641
642-
> 举一个使用 `extern std::mutex` 的完整[运行示例](https://godbolt.org/z/bWv5fcdGf)。当然,其实理论上你 `new std::mutex` 也是完全可行...... 🤣🤣
642+
> 举一个使用 `extern std::mutex` 的完整[运行示例](https://godbolt.org/z/z47x1Es5z)。当然,其实理论上你 `new std::mutex` 也是完全可行...... 🤣🤣
643643
644644
`std::unique_lock` 是灵活的,同样允许在对象销毁之前就解锁互斥量,调用 `unlock()` 成员函数即可,不再强调。
645645
@@ -654,7 +654,7 @@ void process_data(){
654654
```cpp
655655
void f(){
656656
if(!ptr){ // 1
657-
std::lock_guard<std::mutex>lk{ m };
657+
std::lock_guard<std::mutex> lk{ m };
658658
if(!ptr){ // 2
659659
ptr.reset(new some); // 3
660660
}
@@ -755,7 +755,7 @@ private:
755755
756756
public:
757757
void set(const std::string& key, const std::string& value) {
758-
std::lock_guard<std::shared_mutex> lock(mutex_);
758+
std::lock_guard<std::shared_mutex> lock{ mutex_ };
759759
data_[key] = value;
760760
}
761761
@@ -767,7 +767,7 @@ public:
767767
};
768768
```
769769
770-
> [完整代码](https://github.com/Mq-b/ModernCpp-ConcurrentProgramming-Tutorial/blob/main/code/03共享数据/保护不常更新的数据结构.cpp)[测试](https://godbolt.org/z/KG84rb8qd)链接。标准输出可能交错,但无数据竞争。
770+
> [完整代码](https://github.com/Mq-b/ModernCpp-ConcurrentProgramming-Tutorial/blob/main/code/03共享数据/保护不常更新的数据结构.cpp)[测试](https://godbolt.org/z/ezh1Pdo5E)链接。标准输出可能交错,但无数据竞争。
771771
772772
`std::shared_timed_mutex` 具有 `std::shared_mutex` 的所有功能,并且额外支持超时功能。所以以上代码可以随意更换这两个互斥量。
773773
@@ -815,15 +815,15 @@ int main() {
815815
816816
```cpp
817817
void recursive_function(int count) {
818-
std::lock_guard<std::recursive_mutex>lc{ mtx };
818+
std::lock_guard<std::recursive_mutex> lc{ mtx };
819819
std::cout << "Locked by thread: " << std::this_thread::get_id() << ", count: " << count << std::endl;
820820
if (count > 0) {
821821
recursive_function(count - 1);
822822
}
823823
}
824824
```
825825
826-
> [运行](https://godbolt.org/z/rqG613W94)测试。
826+
> [运行](https://godbolt.org/z/d63zrG1cK)测试。
827827
828828
## `new``delete` 是线程安全的吗?
829829

0 commit comments

Comments
 (0)