C++ 线程间通信

async函数用于异步执行任务,可指定立即启动或延迟启动。future用于获取异步任务的结果,不支持拷贝但支持移动构造。promise作为线程间通信的工具,保存值供future读取,只能设置一次。get()和wait()方法用于获取future的结果,wait_for()和wait_until()则监控任务状态。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、async

        1、头文件#include <thread>

        async()会自动创建一个线程去执行函数,返回类型为future。

        函数原型:


//(C++11 起) (C++17 前)
template< class Function, class... Args>
std::future<std::result_of_t<std::decay_t<Function>(std::decay_t<Args>...)>>
    async( Function&& f, Args&&... args );
 
//(C++11 起) (C++17 前)
template< class Function, class... Args >
std::future<std::result_of_t<std::decay_t<Function>(std::decay_t<Args>...)>>
    async( std::launch policy, Function&& f, Args&&... args );

第一个参数是线程创建的策略:

std::launch::async:在调用async就开始创建线程。
std::launch::deferred:延迟加载方式创建线程。调用async时不创建线程,直到调用了future的get或者wait时才创建线程。
默认策略是:std::launch::async | std::launch::deferred

二、future

        使用future可以拿到异步线程函数的返回值。

        future不支持拷贝构造,只支持移动构造,只允许一个future对象有权限获得结果。

        成员函数:

get()会释放原来的指针:

想要实现共享,需要用shared_future

      _Res
      get()
      {
        typename _Base_type::_Reset __reset(*this);
        return std::move(this->_M_get_result()._M_value());
      }
get()阻塞,直到线程函数执行完毕,返回线程函数返回值。get函数会释放future绑定的对象。
wait()在线程函数完成前一直阻塞。
wait_for()等待future对象的异步线程在一段时间段内是否执行完毕,返回future_state。阻塞
wait_until()等待future对象的异步线程在一个时间点是否执行结束,返回future_state。阻塞
share()获取std::future的所有权,移动语义
valid()判断该future对象是否有效

future_state:

deferred异步操作还未开始
ready异步操作已经完成
timeout异步操作超时,主要用于std::future<T>.wait_for()

三、promise

        promise可以保存template<typename T>类型的对象,该值可以被future对象读取(该future对象可能在另一个线程中),是一种线程同步的手段。

        promise只能被set一次。

        promise和future类似于消息的管道,但是是一次性的。

### C++线程间通信的方式 在 C++ 的多线程环境中,线程间通信可以通过多种方法实现。以下是几种主要的线程间通信方式及其特点: #### 1. **互斥锁 (Mutex)** `std::mutex` 是一种常用的同步工具,用于保护共享资源免受多个线程的同时访问。当一个线程锁定互斥锁时,其他试图获取该锁的线程会被阻塞直到锁被释放[^2]。 ```cpp #include <iostream> #include <thread> #include <mutex> std::mutex mtx; // 定义全局互斥锁 void print_block(int n, char c) { std::lock_guard<std::mutex> lock(mtx); // 自动管理锁的生命周期 for (int i = 0; i < n; ++i) { std::cout << c; } std::cout << '\n'; } int main() { std::thread t1(print_block, 50, '*'); std::thread t2(print_block, 50, '$'); t1.join(); t2.join(); return 0; } ``` 上述代码展示了如何通过 `std::mutex` 和 `std::lock_guard` 实现对共享资源的安全访问。 --- #### 2. **条件变量 (Condition Variable)** 条件变量允许线程等待某个特定条件的发生。它通常与互斥锁一起使用,以便在线程之间传递信号。 ```cpp #include <iostream> #include <thread> #include <queue> #include <mutex> #include <condition_variable> std::queue<int> data_queue; std::mutex queue_mutex; std::condition_variable cv; void producer(int id) { int value = 0; while (true) { { std::unique_lock<std::mutex> ul(queue_mutex); data_queue.push(value++); cv.notify_one(); // 唤醒消费者线程 } std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } void consumer(int id) { while (true) { std::unique_lock<std::mutex> ul(queue_mutex); cv.wait(ul, [] { return !data_queue.empty(); }); // 等待数据可用 int value = data_queue.front(); data_queue.pop(); std::cout << "Consumer " << id << ": " << value << "\n"; } } int main() { std::thread p(producer, 1); std::thread c(consumer, 1); p.detach(); c.join(); return 0; } ``` 这段代码演示了生产者-消费者的经典模式,其中条件变量负责协调两个线程的操作。 --- #### 3. **原子变量 (Atomic Variables)** 对于简单的计数器或其他不需要复杂逻辑的数据结构,可以使用 `std::atomic` 提供无锁操作。这有助于减少因加锁带来的开销。 ```cpp #include <iostream> #include <thread> #include <atomic> std::atomic<int> counter{0}; void increment_counter(int num_increments) { for (int i = 0; i < num_increments; ++i) { counter++; } } int main() { const int NUM_THREADS = 10; const int INCREMENTS_PER_THREAD = 100000; std::thread threads[NUM_THREADS]; for (int i = 0; i < NUM_THREADS; ++i) { threads[i] = std::thread(increment_counter, INCREMENTS_PER_THREAD); } for (auto& th : threads) { th.join(); } std::cout << "Final Counter Value: " << counter.load() << "\n"; return 0; } ``` 这里展示了一个基于原子变量的简单计数器示例。 --- #### 4. **共享内存 (Shared Memory)** 虽然严格意义上不属于 C++ 标准库的一部分,但在 POSIX 平台上,可以通过 `shm_open`, `mmap` 等函数创建跨进程或线程的共享内存区域[^3]。然而,在纯 C++线程环境下更推荐使用前三种方式进行通信。 --- ### 总结 C++ 中的线程间通信主要包括互斥锁、条件变量以及原子变量等方式。每种方式都有其适用场景:互斥锁适用于保护临界区;条件变量适合于复杂的事件通知机制;而原子变量则提供了轻量级的并发支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值