@bit::Shadow
✧(≖ ◡ ≖✿
目录
[get VS wait](#get VS wait)
本篇的写作背景是为了"认识 了解"相应接口及性质,不是为了实践级复习。
写给读者:若追求详细、实践 请离开此文章。
1.<thread>线程库
2.std::chrono时间控制类
3.多种多样的锁
lock_guard
unique_lock
recursive_mutex // 递归互斥锁
try_lock // 尝试锁
try_to_lock
std::this_thread::
线程ID获取与线程定时休眠
*使用lambda表达式处理线程调用函数

☆*禁拷贝的锁传参------ref()

注意:x也必须是ref。---编译错误
atomic
整型与指针(常用于)
cpp
#include <iostream>
#include <atomic>
#include <thread>
#include <vector>
std::atomic<int> counter(0); // 原子整型,初始值为 0
void worker() {
for (int i = 0; i < 100000; ++i) {
// 原子自增,等价于 counter.fetch_add(1)
++counter;
}
}
int main() {
std::vector<std::thread> threads;
// 启动 10 个线程
for (int i = 0; i < 10; ++i) {
threads.emplace_back(worker);
}
// 等待所有线程结束
for (auto& t : threads) {
t.join();
}
// 期望结果:10 * 100000 = 1000000
std::cout << "counter = " << counter.load() << std::endl;
return 0;
}
原理
load意为读取原子变量中的值

同时也有
std::atomic::compare_exchange_strong()(使用较少)
内存序
在大量数据下(如果有必要的话)我们可以手动定制内存序(以提升效率):


condition_variable
条件变量 std::condition_variable
std::condition_variable::wait()
std::condition_variable::notify_one()
std::condition_variable::notify_all()
注意:条件变量使用unique_lock限定。(无互斥锁)
cpp
#include <iostream>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <chrono>
std::queue<int> q; // 共享队列
std::mutex mtx; // 保护队列的互斥锁
std::condition_variable cv; // 条件变量
bool finished = false; // 生产者结束标志
// 生产者线程
void producer() {
for (int i = 1; i <= 5; ++i) {
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟生产耗时
{
std::lock_guard<std::mutex> lock(mtx);
q.push(i);
std::cout << "生产者生产: " << i << std::endl;
} // 离开作用域自动解锁
cv.notify_one(); // 通知一个等待的消费者
}
// 生产结束,设置标志并唤醒消费者
{
std::lock_guard<std::mutex> lock(mtx);
finished = true;
}
cv.notify_one();
}
// 消费者线程
void consumer() {
while (true) {
std::unique_lock<std::mutex> lock(mtx);
// 等待条件成立:队列非空 或 生产结束
// 使用 lambda 防止虚假唤醒(spurious wakeup)
cv.wait(lock, [] { return !q.empty() || finished; });
// 如果队列空了且生产结束,退出循环
if (q.empty() && finished) {
break;
}
// 取出数据
int value = q.front();
q.pop();
std::cout << "消费者消费: " << value << std::endl;
lock.unlock(); // 处理完数据后可以提前解锁(可选)
}
std::cout << "消费者结束" << std::endl;
}
int main() {
std::thread t1(producer);
std::thread t2(consumer);
t1.join();
t2.join();
return 0;
}
async与future
异步执行与延迟执行
async
auto的类型是std::future

cpp
void task(const char* name) {
std::cout << name << " 开始执行, 线程ID: "
<< std::this_thread::get_id() << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << name << " 完成" << std::endl;
}
int main() {
std::cout << "主线程ID: " << std::this_thread::get_id() << std::endl;
// 异步执行(新线程)
auto f1 = std::async(std::launch::async, task, "异步任务");
// 延迟执行(调用get时执行)
auto f2 = std::async(std::launch::deferred, task, "延迟任务");
std::cout << "主线程工作..." << std::endl;
f1.get(); // 等待异步任务完成
f2.get(); // 此时才执行延迟任务
return 0;
}
async异步与线程的区别
"async"是线程的轻量化管理体系。
std::thread 给你一个裸线程,你自己管一切;std::async 给你一个"任务",库帮你管执行和结果。(我们使用时从其便捷的接口就可以得出)
future
std::future 是 C++11 引入的用于访问异步操作结果的类模板。它代表一个"未来会得到的结果",你可以通过它获取另一个线程(或延迟任务)计算出的值。
核心成员函数:get() wait() wait_for()/wait_until()
get VS wait
| 对比项 | wait() |
get() |
|---|---|---|
| 返回值 | 无(void) |
任务的返回值 |
| 是否取走结果 | ❌ 不取,结果仍留在 future 里 | ✅ 取走,future 变为无效状态 |
| 能否重复调用 | ✅ 可以多次 | ❌ 只能调用一次 |
| 异常处理 | 不抛出任务里的异常 | 会重新抛出任务里的异常 |
| 对共享状态的影响 | 保持不变 | 使 future 失效(valid() == false) |
promise
内部封装了future,主要用于get()、wait() 取结果。
set_value( )与set_value_at_thread_exit(),在不同时机设置get()的结果值。set_value() 直接唤醒get(若有) set_value_at_thread_exit()不会立即唤醒get()(若有)只有在任务结束后才会。
注意:二者均线程不安全
shared_future
实现了让多个线程(或从多个地方)能够安全地读取同一个异步结果。(get() . . .)
package_task
封装了promise、future的结合体

**用例线程池代码
cpp
class ThreadPool {
public:
// 构造函数,启动指定数量的工作线程
ThreadPool(size_t threads) : stop(false) {
for (size_t i = 0; i < threads; ++i) {
workers.emplace_back([this] {
for (;;) {
std::function<void()> task;
{
std::unique_lock<std::mutex> lock(this->queue_mutex);
// 队列为空,始终wait阻塞
this->condition.wait(lock,
[this] { return this->stop || !this->tasks.empty(); });
// 线程池退出
if (this->stop && this->tasks.empty())
return;
task = std::move(this->tasks.front());
this->tasks.pop();
}
task();
}
});
}
}
// 向线程池添加任务
template<class F, class... Args>
auto enqueue(F&& f, Args&&... args)
-> std::future<typename std::result_of<F(Args...)>::type> {
using return_type = typename std::result_of<F(Args...)>::type;
//std::packaged_task <return_type()>* ptask = new std::packaged_task <return_type()>()
auto task = std::make_shared<std::packaged_task<return_type()>>(
std::bind(std::forward<F>(f), std::forward<Args>(args)...)
);
std::future<return_type> res = task->get_future();
{
std::unique_lock<std::mutex> lock(queue_mutex);
// 不允许在停止线程池后添加新任务
if (stop)
throw std::runtime_error("enqueue on stopped ThreadPool");
tasks.emplace([task]() { (*task)(); });
}
condition.notify_one();
return res;
}
// 析构函数,等待所有任务完成
~ThreadPool() {
{
std::unique_lock<std::mutex> lock(queue_mutex);
stop = true;
}
condition.notify_all();
for (std::thread& worker : workers)
worker.join();
}
private:
// 工作线程集合
std::vector<std::thread> workers;
// 任务队列
std::queue<std::function<void()>> tasks;
// 同步原语
std::mutex queue_mutex;
std::condition_variable condition;
bool stop;
};
本篇完