面试七、单线程异步、多线程异步、协程

 1. 单线程异步    

        在单线程的异步模型中,异步操作通常通过事件循环机制来处理。当一个异步操作被启动后,程序会继续执行其他任务,但异步操作的结果或者状态变化会被放入事件队列中,等待事件循环处理。当事件循环处理到该事件时,会调用相应的回调函数来处理操作的结果或者状态变化。在这种情况下,不需要重新开启一个线程来执行其他任务。

  1. 非阻塞I/O操作: 单线程与事件循环模型中的I/O操作通常采用非阻塞的方式进行,即在发起I/O操作后,程序不会等待操作完成,而是立即返回继续执行后续的任务。这样,单线程在处理一个I/O操作时不会被阻塞,可以立即切换到处理其他任务,从而提高了程序的并发能力和响应速度。

  2. 事件驱动的设计: 单线程与事件循环模型采用事件驱动的设计思想,通过事件循环轮询监听各种事件的发生,例如网络数据的到达、定时器的触发、用户输入等。当某个事件发生时,事件循环会调用相应的事件处理函数来处理事件。这种设计使得程序能够同时处理多个I/O操作,而不需要为每个操作创建一个线程,节省了线程切换的开销。

  3. 异步回调函数: 单线程与事件循环模型通常使用异步回调函数来处理I/O操作的结果。在发起一个I/O操作时,可以指定一个回调函数,当操作完成时,系统会调用该回调函数来处理操作的结果。这种方式使得程序在等待I/O操作完成时不会被阻塞,能够继续执行其他任务,提高了程序的并发能力和吞吐量。

#include <iostream>
#include <queue>
#include <functional>

// 定义事件类型
enum EventType {
    EVENT_TYPE_MESSAGE,
    EVENT_TYPE_TIMER
};

// 事件结构体
struct Event {
    EventType type;
    std::function<void()> handler;
};

// 事件循环类
class EventLoop {
private:
    std::queue<Event> eventQueue; // 事件队列

public:
    // 注册事件处理器
    void addEvent(EventType type, std::function<void()> handler) {
        eventQueue.push({type, handler});
    }

    // 事件循环
    void run() {
        while (!eventQueue.empty()) {
            Event event = eventQueue.front();
            eventQueue.pop();

            // 调用事件处理函数
            event.handler();
        }
    }
};

int main() {
    // 创建事件循环对象
    EventLoop eventLoop;

    // 注册消息事件处理器
    eventLoop.addEvent(EVENT_TYPE_MESSAGE, []() {
        std::cout << "Processing message..." << std::endl;
    });

    // 注册定时器事件处理器
    eventLoop.addEvent(EVENT_TYPE_TIMER, []() {
        std::cout << "Processing timer..." << std::endl;
    });

    // 启动事件循环
    eventLoop.run();

    return 0;
}

2. 多线程异步

        多线程异步编程模型通常使用多个线程来处理异步任务,每个线程可以独立地执行任务,并且任务之间可以并行执行,从而提高了程序的并发能力和性能。

#include <iostream>
#include <future>
#include <thread>
#include <chrono>

// 异步任务函数,模拟计算密集型任务
int calculate(int a, int b) {
    std::this_thread::sleep_for(std::chrono::seconds(2)); // 模拟耗时操作
    return a + b;
}

int main() {
    // 创建一个异步任务,计算两个数的和
    std::future<int> futureResult = std::async(std::launch::async, calculate, 10, 20);

    // 主线程可以继续执行其他任务
    std::cout << "Main thread continues executing other tasks..." << std::endl;

    // 等待异步任务完成并获取结果
    int result = futureResult.get();

    // 打印计算结果
    std::cout << "Result of calculation: " << result << std::endl;

    return 0;
}

3. 协程

什么是协程? - 知乎 (zhihu.com)

        协程这个技术已经过时了,使用线程可以发挥多核的优势。在有大量IO操作业务的情况下,我们采用协程替换线程,可以到达很好的效果,一是降低了系统内存,二是减少了系统切换开销,因此系统的性能也会提升。

        协程运行在线程之上,当一个协程执行完成后,可以选择主动让出,让另一个协程运行在当前线程之上。协程并没有增加线程数量,只是在线程的基础之上通过分时复用的方式运行多个协程,而且协程的切换在用户态完成,切换的代价比线程从用户态到内核态的代价小很多。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值