多线程程序开发简介

多线程程序开发简介

多线程程序开发简介

  • 一、线程 / Threading- 二、使用线程的几种方式-

    一、线程 / Threading

    线程这个概念大概在1993年后才慢慢流行起来。线程是操作系统进行调度的最小单位,拥有少量的资源,如寄存器和栈。线程的特点是共享地址空间,从而高效地共享数据。多线程的价值是更好地发挥多核处理器的功能。

    二、使用线程的几种方式

    1. 流水线

    每个线程反复地在数据系列集上执行同一种操作,并把操作结果传递给下一步骤的其他线程,这就是流水线方式

    在流水线方式中,数据元素流串行地被一组线程顺序处理。每个线程依次在每个元素上执行一个特定的操作,并将结果传递给流水线中的下一个线程。

    在这里插入图片描述

    2. 工作组

    每个线程在自己的数据上执行操作。工作组中的线程可能执行同样的操作,也可能执行不同的操作,但是它们一定独立地执行。

    工作组模式中,数据由一组线程分别独立处理。通常有两种模式:SIMD(single instruction, multiple data, 单指令多数据流)和MIMD(multiple instruction, multiple data, 多指令多数据)。SIMD是指所有的工作线程在不同的数据部分上执行相同的操作,MIMD是指工作组中的线程在不同的数据上执行不同的操作。

    在这里插入图片描述

    3. 客户端 / 服务器

    一个客户端为每一件工作与一个独立的服务器“订契约”。通常“订契约”是匿名的,一个请求通过某种接口提交。

    在客户服务器系统中,客户端请求服务器对一组数据执行某个操作。服务器独立地执行操作——客户端或者等待服务器执行,或者并行地执行,在后面需要时再查找结果。

    在这里插入图片描述

    三、线程的好处

    多线程编程具有如下优点:

    • 在多处理器系统中开发程序的并行性。并行性这一优点需要特殊硬件支持,其他优点对硬件无要求。- 在等待慢速外设I/O操作结束的同时,程序可以执行其他计算,为程序的并发提供更有效、更自然的开发方式。- 一种模块化编程模型,能清晰地表达程序中独立事件间的相互关系。

    四、线程的代价

    1. 计算负荷

    线程代码中的负荷包括由于线程间同步所导致的直接影响。很多算法在某些情况下可避免同步,但在几乎任何线程代码中都需要使用某种同步机制,同步很容易损失性能。

    计算密集型线程数量若比可用的处理器多,则可能比单线程实现获得更好的代码结构,但程序性能也会更糟,这是由于多线程结构在要完成的工作上增加了同步和调度开销,而可用的资源并没有变。

    2. 编程规则

    线程模型基本思想简单,但编写能在多线程中良好工作的代码需要认真思考和规划,包括同步协议,避免死锁、竞争和优先级倒置。如果有可用的库,应尽量使用库代码而不是自己编写。

    3. 更难以调试

    调试不可避免的改变了事件的时序,这对于串行代码问题不大,但对于异步代码却是致命的。一个线程因调试陷阱而运行得慢了,要跟踪的问题可能就不会出现,调试无法再现的错误是一件让人头疼的事情。

    五、多线程适用场合

    从功能上讲,没有什么是多线程能做到而单线程做不到的,反之亦然。

    如果用很少的CPU负载就能让IO跑满,或者用很少的IO流量就能让CPU跑满,那么多线程就没有什么优势。

    多线程的适用场景是:提高响应速度,让IO和“计算”相互重叠,降低延迟。虽然多线程不能提高绝对性能,但能提高平均响应性能。

    一个程序要写成多线程,大致要满足:

    · 有多个CPU可用,单核机器上多线程无性能优势; · 共享的数据是可以修改的; · · 延迟和吞吐量同样重要,不是简单的IO密集或CPU密集型程序; · 可扩展,一个好的多线程程序应能享受增加CPU数目带来的好处;
    · 多线程能有效地划分责任与功能,让每个线程的逻辑简单,任务单一,便于编码。

    六、多线程常用编程模型

    多线程常用编程模型有如下几种:

    · 每个请求创建一个线程,使用阻塞式IO操作(伸缩性不佳); · 使用非阻塞IO+IO多路复用;
    · Leader/Follower等高级模式;

    1. one loop per thread

    此模型下,程序里的每个IO线程有一个event loop(用作IO多路复用),用于处理读写和定时时间。event loop代表了线程的主循环,需要让哪个线程干活,就把timer或IO channel注册到哪个线程的loop里即可。

    event loop描述如下:

    while there are still events to process:
        e = get the next event
        if there is a callback associated with e:
            call the callback

    2. Leader / Follower

    此模型会创建一个线程池,每个线程有三种状态:leading, following, processing。Leader线程负责监听请求,其他线程作为follower处于等待状态,当leader收到请求后,首先通知一个follower线程将其提拔为新的leader,然后自己去处理这个请求,处理完毕后加入follower线程等待队列,等待下次成为leader。

    Leader/Follower模式避免了线程动态创建和销毁的额外开销,将线程放在池中,无需交换数据,将上下文切换、同步、数据移动和动态内存管理的开销都降到了最低。

    在这里插入图片描述

    3. 推荐模式

    推荐的多线程编程模式:one loop per thread + 线程池

    event loop用作IO多路复用,配合非阻塞IO和定时器;线程池用作计算,可以是任务队列或生产者消费者队列。

    小结

    线程无法给所有编程问题提供最好的解决方案。线程并不总是容易使用,也不能保证总是提供更好的性能。某些问题本身是非并发的,使用线程只能降低程序的性能并使程序复杂。大部分程序有一些本质上的并发,这种情况下,多线程程序通常比串行程序更快、响应性能更好,而且比实现同样功能的非线程异步程序更易于开发和维护。

posted @ 2021-01-04 15:18  刘桓湚  阅读(364)  评论(0编辑  收藏  举报