c++多线程4

211 阅读3分钟

异步操作(重点)

异步(Asynchronous)编程是一种编程范式,允许程序在等待某些操作(如 I/O、网络请求、计算任务等)完成时继续执行其他任务,而不是阻塞当前线程。异步编程可以提高程序的并发性和响应性,特别是在处理耗时操作时。

  • std::future:异步指向某个任务,然后通过future特性去获取任务函数的结果。用于获取异步任务的结果。
  • std::async:异步启动运行某个任务函数。
  • std::packaged_task:将任务和future绑定在一起的模版,是一种封装对人物的封装。(可移动的对象,需要move移动)
  • std::promise:线程1设置了某个值,通知另外的线程2。(例如:你在A中创建了一个值,那么B如何找到这个值呢?所以用到了promise)
//future and async
int func(){
    int i;
    for(i =0;i<1000;i++){
        cout<<"func"<<i<<endl;
    }
    return i;
}
int main(){
    std::future<int> future_result=std::async(std::launch::async,func);
// 启动异步任务

    cout<<func()<<endl;
    cout<<future_result.get()<<endl;
}
int func(){
    int i;
    for(i =0;i<1000;i++){
        cout<<"func"<<i<<endl;
    }
    return i;
}
int main(){
    std::packaged_task<int()> task(func);//它只是把函数包成对象,并没有启动
    auto future_result = task.get_future();//获取future对象
    //如果要启动task
    std::thread t(std::move(task));//一旦开始运行,结果放到future对象里
    t.join();
    cout<<func()<<endl;
    cout<<future_result.get()<<endl;
}
#include <iostream>
#include <future>
#include <thread>
using namespace std;

void task(promise<int> prom) {
    this_thread::sleep_for(chrono::seconds(2)); // 模拟耗时操作
    prom.set_value(42); // 设置结果
}

int main() {
    promise<int> prom;
    future<int> fut = prom.get_future(); // 获取 future 对象

    thread t(task, move(prom)); // 启动线程并传递 promise
    cout << "Waiting for result..." << endl;
    int value = fut.get(); // 获取结果(会阻塞直到结果可用)
    cout << "Result: " << value << endl;

    t.join();
    return 0;
}

bind

绑定函数:将函数与部分或全部参数绑定,生成一个新的可调用对象。

  1. 只是绑定函数,参数我们自己传入 手动传入
  2. 绑定函数的时候,也把参数绑定
(1)绑定普通函数
#include <iostream>
#include <functional>
using namespace std;
using namespace placeholders; // 引入占位符

void printSum(int a, int b) {
    cout << "Sum: " << a + b << endl;
}

int main() {
    auto boundFunc = bind(printSum, 10, _1); // 绑定第一个参数为 10
    boundFunc(20); // 相当于调用 printSum(10, 20)
    return 0;
}

输出

Sum: 30
(2)绑定成员函数
#include <iostream>
#include <functional>
using namespace std;
using namespace placeholders;

class Math {
public:
    void printSum(int a, int b) {
        cout << "Sum: " << a + b << endl;
    }
};

int main() {
    Math math;
    auto boundFunc = bind(&Math::printSum, &math, _1, _2); // 绑定成员函数
    boundFunc(10, 20); // 相当于调用 math.printSum(10, 20)
    return 0;
}

输出:

Sum: 30
(3)绑定函数对象
#include <iostream>
#include <functional>
using namespace std;

struct Adder {
    int operator()(int a, int b) const {
        return a + b;
    }
};

int main() {
    Adder adder;
    auto boundFunc = bind(adder, _1, 10); // 绑定第二个参数为 10
    cout << "Result: " << boundFunc(20) << endl; // 相当于调用 adder(20, 10)
    return 0;
}

输出:

Result: 30

 std::bind 的高级用法

(1)调整参数顺序
#include <iostream>
#include <functional>
using namespace std;
using namespace placeholders;

void printDifference(int a, int b) {
    cout << "Difference: " << a - b << endl;
}

int main() {
    auto boundFunc = bind(printDifference, _2, _1); // 调整参数顺序
    boundFunc(10, 20); // 相当于调用 printDifference(20, 10)
    return 0;
}

输出:

Difference: 10
(2)部分绑定
#include <iostream>
#include <functional>
using namespace std;
using namespace placeholders;

void printProduct(int a, int b, int c) {
    cout << "Product: " << a * b * c << endl;
}

int main() {
    auto boundFunc = bind(printProduct, _1, 2, _2); // 绑定第二个参数为 2
    boundFunc(3, 4); // 相当于调用 printProduct(3, 2, 4)
    return 0;
}

输出:

Product: 24

5. std::bind 与 Lambda 表达式的对比

std::bind 的功能可以用 Lambda 表达式实现,但 Lambda 表达式通常更直观和灵活。

示例:使用 Lambda 表达式替代 std::bind

#include <iostream>
using namespace std;

void printSum(int a, int b) {
    cout << "Sum: " << a + b << endl;
}

int main() {
    auto lambdaFunc = [](int b) { printSum(10, b); }; // 使用 Lambda 表达式
    lambdaFunc(20); // 相当于调用 printSum(10, 20)
    return 0;
}

输出:

Sum: 30