使用线程和协程
首先理解线程和协程,线程是进程中使用,一个进程至少一个线程,协程是线程中使用,在windows中使用可以使用纤程,linux下本身有协程的概念和api,当然很多单独的库做的很好,可以引用使用。
一、线程
在程序中使用线程是必不可少的,主线程往往阻塞甚至来不及反应,如何解决这种问题,使用线程就好,stl 加入了标准线程之后,c++ 实在好用多了,当然无论windows或者linux等等操作系统也有api可以直接使用,不过使用stl 标准,省去了写多套代码的时间,生产力提高了。
std::thread thd1([this,&flag]() {
for (;;)
{
cout << "the flag is:" << flag << endl;
if (flag && 1 == 1)
{
if (v_f != nullptr)
v_f();
}
else
std::this_thread::yield();
}
});
这样立刻启动了一个线程,使用lamba函数也是c++标准库的好处,其实c++ 已经很好用了,那为什么要使用协程呢?
二、协程
void decode1()
{
for (int i = 0; i < 1000; ++i)
{
std::cout << "test 1 => " << i << std::endl;
coroutine::yield();
}
}
void decode2()
{
for (int i = 0; i < 1000; ++i)
{
std::cout << "test 2 => " << i << std::endl;
coroutine::yield();
}
}
以上所代码,两个函数都是死循环函数【假定】, 如果使用两个线程执行,cpu是在线程间上下文切换的,当然,使用多核cpu问题不大,虽然依然会调度,
调度问题:
- 调度问题
- 两个线程需要协调资源,互相等待
- 或者某一个线程需要等待信号的时候,线程时间无法工作,不是wait 就是sleep了
- 异步问题
- 异步网络等待网络包
- 回调函数过多,引起不适
场景:等待网络包解码,假定以上两个函数位解码h264和h265的线程,不可能把一个线程沾满,必然要等待进入网络包队列不为空,这是函数wait或者sleep,如果使用协程,线程在两个协程中切换,显然哪个队列包过来就开始解码,这样有三个benefit
1 减少了1个线程
2 提高了线程利用率
3 如果两个线程中有互相锁定的资源,现在可以去掉锁定,因为在一个线程中执行。
三、总结
使用协程的好处已经不言而喻了,尤其在服务器程序中,等待无数个人的网络包过来,单网卡收包使用协程是很自然的,处理耗时的地方另作线程,对于异步网络库来说,不用写过多的回调也是一大好处,代码更容易理解。
这里是一个不用其他库的协程使用方法封装,适用于windows和linux,已经经过测试
兼容协程封装下载
如果只需要windows,可以从这里下载
windows fiber 下载