0%

C++11 中的线程库 thread 与同步库 mutex

C++11 提供了线程库和同步库,可以屏蔽操作系统接口细节使用多线程了

多线程

std::thread 创建与使用

std::this_thread 当前线程

线程同步

lock_guard 互斥锁

unique_lock + condition_variable 条件锁

原子操作库

实现轻量免锁的多线程安全操作

https://zh.cppreference.com/w/cpp/atomic/atomic

https://zh.cppreference.com/w/cpp/atomic/atomic_flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
std::atomic_int ttt;
void test(bool add) {
for (int i = 0; i < 100000; ++i) {
if (add) ++ttt;
else --ttt;
}
printf("th exit!\n");
}
int main() {
ttt = 0;
std::vector<std::thread> ths;
for (int i = 0; i < 4; ++i) {
ths.emplace_back(test, i % 2 == 0);
}
for (auto& th : ths) {
th.join();
}
std::cout << ttt << std::endl;
return 0;
}

输出为 0; 如果把头一行的 std::atomic_int 换成 int, 得到的结果偏差巨大

异步任务 future & promise

定义于 <future> 头文件

使用 future 三种方式: packaged_task, promise, async

https://zh.cppreference.com/w/cpp/thread/future

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <future>
#include <thread>

int main()
{
// 来自 packaged_task 的 future
std::packaged_task<int()> task([](){ return 7; }); // 包装函数
std::future<int> f1 = task.get_future(); // 获取 future
std::thread(std::move(task)).detach(); // 在线程上运行

// 来自 async() 的 future
std::future<int> f2 = std::async(std::launch::async, [](){ return 8; });

// 来自 promise 的 future
std::promise<int> p;
std::future<int> f3 = p.get_future();
std::thread( [&p]{ p.set_value_at_thread_exit(9); }).detach();

std::cout << "Waiting..." << std::flush;
f1.wait();
f2.wait();
f3.wait();
std::cout << "Done!\nResults are: "
<< f1.get() << ' ' << f2.get() << ' ' << f3.get() << '\n';
}

std::async

最简单的异步任务使用

1
2
std::launch::async // 运行新线程, 以异步执行任务
std::launch::deferred // 调用方线程上首次请求其结果时执行任务(惰性求值)
1
2
3
4
// 马上开始异步任务
std::future<int> f2 = std::async(std::launch::async, [](){ return 8; });
f2.wait(); // 阻塞至结果变得可用
int result = f2.get(); // 获取结果