C++应用程序优化之三线程的优化

C++应用程序优化之三线程的优化

一、多线程

1、多线程的介绍

多线程编程,现在基本上在各个平台上都普及了。多线程较之于单线程的优势,就类似于多个人干活和一个干活的道理。道理很简单,可是大家都知道,多人干活如果管理不好,未必会产生1+1>=2甚至可能还不如一个人干活更快。
这就涉及到了多线程的应用的场景和多线程的分配管理。这里不介绍线程和多线程的概念,大家如果有兴趣可以自行查找相关的资料。

2、多线程的特点

多线程的特点在于:并行性,无序性,竞争性。而实际的工作任务中,却要解决好顺序性和竞争性。从而使并行的优势保持为最大化。这就要引入同步、互斥以及原子等各种方式来处理。

二、线程的优化

在c++中,线程一般分为以下几类,原始的线程,即操作系统直接提供的线程生成接口API,这是所有的线程的基础。然后是c++的标准库提供的线程库,然后是其它各方提供的封装的线程库。优化从下面的几个层面进行展开。

1、原始线程的优化

原始线程的优化在于:
减少锁的数量:能不加锁的尽量不加锁,尽量全并锁。
减少锁的粒度:使用锁时,注意锁的范围尽量小,防止死锁。
减少竞争(从设计上就得考虑):这个其实就是尽量让线程单独并行,减少之间的数据交互。
减少线程中的循环,避免死循环:死循环会轻易占满一个核心的算力。线程的工作如果必须要死循环的,一定要提供切换机制(sleep(0)之类)。
线程要有退出机制:能回收的线程,尽量要考虑好退出机制,不要存在线程长期等待信号却啥也不干。白白消耗资源。
线程的数量和并行的核心成合理比例:这个是一个经验,线程太多,其实意义也就不大,线程的上下文切换其实也是需要时间的。举一个极端的例子,四个核心,八百个线程,未必是好事。
防止惊群:如果很多线程都等待在一个事件上,一旦这个事件被通知,所有的线程都会被唤醒,但真正最后得到工作机会的可能只有一个,这个现象就叫惊群,写多线程程序,一定要防止这种情况,防止的方法目前来看以限制拿到等待机会的数量为主。

2、库线程的优化

这里主要指标准库的优化,其它库的优化得看具体的情况。c++标准库中的优化,除了可以考虑上面的原生线程的优化方案外,还可以考虑下面几点:
有条件的情况下,使用std::async 替代std::thread。原因是前者复用了线程,可以提高利用率。
c++库中提供了无锁编程(CAS),CAS其实并不是无锁,而是把上层的软件锁移到了硬件层次的原子性操作上,再辅以适当的软件操作来达到的。无锁的编程最近在一些场合(比如固态硬盘的写入)应用很迅速,但是无锁编程有一个劣势,就是它无法保证顺序,这样就需要设计者来进行考虑架构了。

3、线程的操作系统相关

线程的操作往往不是说用库全用库,原生全原生,可能在不同的环境下,或者维护一个庞大的软件,会出现交织复杂的情况。这时候儿,就得根据实际情况来取舍。举一个简单的例子,在Windows多线程编程中,没有条件变量这个同步方式,而在Linux没有Event和临界区这两个同步类型。
当然,可能随着技术的前进,这些都会弥平,但是在处理实际问题时,还是要小心谨慎,防止出现低级错误。

4、线程的并行(计算机和操作系统支持)

多线程编程和并行编程,其实是有区别的,并行编程更复杂,不过在常见的单机情况下二者基体没有太大的差别。并行编程有一些专门的库如OpenMP,但是并行编程的库对环境有一定的要求,有些目前不是支持的很好或者干脆不能支持。这个一定要引起注意。

5、多线程的常见错误

多线程编程的错误非常多,举几个常见的例子:
死锁:多个线程互相持有彼此的资源且不释放。解决的方法就是打破死锁的四个条件任何之一即可。
线程共用数据的释放:这个不光新手,老手也经常遇到,多个线程共用一个指针数据,结果有一个提前释放,引起程序的崩溃。有一种特别经典的现象,就是程序运行没问题,关闭时崩溃,大多是这种情况。
Linux系统上的条件变量的处理:在Linux系统上,会有误触发的情况,一定要处理好。方法是增加一个bool值,进行判断,如果正常,则进行工作,否则再次进入等待。
多线程编程错误有很多,这里不再一一列举,多线程编程易学难精,这是大家公认的。所以不要掉以。

三、总结

设计多线程最好的方式,其实是把业务完全拆开,达到各个线程之间互不交互才是最好的(但实际情况往往不能这样),这样的结果,可以极大的发挥CPU的全部算力。因此,优化多线程的问题的首要核心其实是设计上尽量减少多线程交互而不是在交互过程中进行优化。
同时,一些优秀的c++库正在把协程引入到c++中,协程的优势在于可以复用CPU,减少上下文的切换,所以这也是可以考虑的方向,在c++20中,可能协程就会被引入进来。
关注新技术动向,也是优化多线程的一个重要的方式。

发布了104 篇原创文章 · 获赞 12 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/fpcc/article/details/88973543
今日推荐