2019独角兽企业重金招聘Python工程师标准>>>

(一) 前言

作为一名优秀的攻城师,了解多线程的知识非常有必要,尤其在人工智能和机器学习的热潮下,如何提高程序或者算法的运行效率是非常有价值的一件事情。

在当代大多数的操作系统,都有能力同时的运行多个程序或者app,比如在windows上你可以同时打开多个QQ,多个不同的浏览器,多个不同的视频播放器。或者在你的苹果或者安卓手机上边听歌边使用地图功能,这背后其实用的就是用的是多线程的技术。

(二)多任务处理

在同一时刻运行多个程序也叫做多任务处理,每个程序会由一个单独的task来执行,每个task运行在一个单独的处理器中(可以理解为是一个进程或者一个CPU)。在早期的计算机操作系统中,往往都是单处理器的,这时候你也能同时运行多个程序,这种情况我们称为并发而不是并行,因为这个时候多个程序其实是共用的一个CPU时钟,由于计算机的时间片切换非常快,所以大多数时候你是感觉不到这种差异的,但其实是一种假象。随着社会的进步,现在的电脑基本上都是多个CPU的,所以在多个CPU的情况下,程序才能够真正的并行起来。

(三)线程与多线程

每个处理器可以创建多个子任务,这里的每一个子任务都是一个线程。一个线程执行的其实就是一段代码指令序列。在一个处理器内的多个线程是可以通过处理器的共享内存进行交互的,关键词并发(concurrency)指的就是在一个处理器内同时执行多个线程。

多线程通常是通过把大的任务切分成多个子任务运行,以此来提高程序运行效率的。比较典型的例子就是现实中修一段高速公路时,最快的方法就是,把这条公路切分成多段,然后每个段由一个工程队负责,这样同时工作就能大大提高效率。

(四)并发与线程上下文切换

上面说过,单个处理器内的多线程任务其实是一种假象,其实是通过切换CPU时钟实现的,这个时候,在切到另一个线程之前,CPU必须保存当前线程的状态,这被称为上下文切换,这也是单核处理器能同时执行多个任务的秘密。

线程切换是一个比较昂贵的操作,调度器需要花费额外的CPU时间来临时暂停当前活跃的线程为了让另外一个线程运行,然后保存当前线程状态,在需要的时候,还得恢复当前挂起的线程状态。

(五)线程调度

线程调度主要负责线程的上下文切换,它决定了接下来要选择哪个挂起的线程执行。线程调度是操作系统的一部分。

(六)互斥

互斥的目的是保证在两个线程之间不能同时执行同一个代码片段。通俗点来说就是我们在大街上看到的红绿灯,任何时候只能有一种颜色的灯在亮。 互斥的资源通常是需要被共享的,比如卫生间的马桶,任何时候只能有一个人用,如果同时有多个人用那么就会出现问题,这也叫竞争,反映到程序中,可能是一种数据解构,一个外部设备如打印机,或者一个网络连接。

竞争通常会带来问题,所以在程序中通常使用锁机制(lock)来达到互斥的目的,互斥也可以称为线程同步(synchronization)

同步带来的缺点是,在一个线程没有释放锁之前,另外一个线程需要一直等待。它强制调度是串行操作的,即使这里有多个空闲的CPU资源,所以在日常开发中要合理使用。

(七)并发与并行

并行:

并行指的是多线程运行在不同的CPU或者处理器上,从而避免了在同一个CPU或者处理器中的上下文切换的操作。当然这里是多个线程之间不需要通信或者有共享资源需要访问。这种情况就可以独立的执行和计算。当然前提是硬件有多个CPU或者处理器。

并发:

并发指的是多个线程有通信或者需要访问共享的数据,这个时候需要考虑加锁,否则有可能安全问题。通常情况下并发是指运行在同一个CPU或者core内,但这并不是十分准确,多个线程也可以运行在多个CPU内但是他们有合理的同步策略。

(八)多处理器 vs 多core vs 超线程

多处理器是指在单台电脑上有多个CPU单元,每一个处理器可以有多个core,每个core可以运行一个任务,多线程程序每个线程都可以并行的运行在一个core中。

注意单个core也有可能运行两个并行的线程,这种能力被称为超线程。

超线程(HT, Hyper-Threading)[1]是英特尔研发的一种技术,于2002年发布。超线程技术原先只应用于Xeon 处理器中,当时称为“Super-Threading”。之后陆续应用在Pentium 4 HT中。早期代号为Jackson。 <br/> 通过此技术,英特尔实现在一个实体CPU中,提供两个逻辑线程。之后的Pentium D纵使不支持超线程技术,但就集成了两个实体核心,所以仍会见到两个线程。超线程的未来发展,是提升处理器的逻辑线程。英特尔于2016年发布的Core i7-6950X便是将10核心的处理器,加上超线程技术,使之成为20个逻辑线程的产品。

超线程其实是一个CPU单元内,提供了两个逻辑线程,依赖于底层操作系统,如果操作系统不支持,也可以禁用掉。因此在一个4 core 处理器系统中可能有8个逻辑处理器。

(九)线程 与 CPU缓存

依赖于CPU的类型,当前的操作系统基本都支持三级缓存,CPU缓存的目的是为了CPU访问CPU缓存数据更快,这种快是相对于CPU读取内存数据而言(RAM),通常情况下一般高出几个数量级。

L1 级别缓存 在cpu的芯片中,体积一般是8-64kb

L2 级别缓存 通常位于CPU和RAM之间,体积一般是2-4MB

L3 级别缓存 如果存在一般都位于主板上,体积一般是8-16MB (注:跟CPU类型有关,一些CPU类型可能直接用L2替代L3了)

下面通过表格看下不同的介质,访问的耗时情况,其中L1缓存属于core级别的,所以每个运行在core里面的线程都可以拥有自己的local cache。

从CPU到 大约需要的CPU周期 大约需要的时间(单位ns)
寄存器 1 cycle 可以忽略
L1 Cache ~3-4 cycles ~0.5-1 ns
L2 Cache ~3-4 cycles ~0.5-1 ns
L3 Cache ~3-4 cycles ~0.5-1 ns
跨槽 ~30-40 cycles ~20 ns
内存 ~120-240 cycles ~60-120ns

(十) 总结

本篇主要介绍了多线程有关的一些基础概念以及CPU的cache模型,在一个多线程的程序中,为了提高处理性能,每个线程都有自己的CPU缓存,而同时如果多个线程想要访问一块共享的区域(位于主内存中),需要考虑同步和可见性的问题,,所以一些编程语言如C,C++,C#和Java都会有确保变量在修改之后对其他线程可见的语义,如Java里面的volatile关键词会强制flush线程的local cache的数据到主存中,除此之外一些锁机制也会触发,如lock和unlock指令,这些知识点会在后面的文章中一一介绍。

参考文章:

https://www.logicbig.com/quick-info/programming/multi-threading.html#processor-cache

https://medium.com/@bkodirov/threading-in-java-55ec2e184fe7

转载于:https://my.oschina.net/u/1027043/blog/1831158

多线程基础知识了解一下相关推荐

  1. Java多线程基础知识

    多线程基础知识 这是我再次学习多线程知识的一个总结,对于刚刚接触的学习者是比较友好易懂的,便于快速的理解和掌握. 一.基本概念: 1.进程:进程就是运行中的程序,当一个程序开始执行,操作系统就会给这个 ...

  2. 【多线程】多线程基础知识

    文章目录 1. 认识线程(Thread) 2. Thread 类及常见方法 2.1 Thread 常见构造方法 2.2 start 和 run 方法的区别 2.3 Thread 常见属性 2.4 中断 ...

  3. Java这些多线程基础知识你会吗?

    0.并发和并行.进程核线程.多进程和多线程的区别: (这里的时间和时刻上的概念同物理上的一样) 并发:在一段时间内多个任务同时执行,或者说是在一段很短的时间内可以执行多条程序指令,微观上看起来好像是可 ...

  4. thread.sleep是让哪个线程休眠_Java多线程:多线程基础知识

    点击上方☝SpringForAll社区 轻松关注!及时获取有趣有料的技术文章 本文来源:https://www.cnblogs.com/ITtangtang/p/7602363.html 一.线程安全 ...

  5. JAVA中多线程基础知识

    程序(软件):数据和指令的集合.软件架构:B/S  C/S  软件分类:系统软件,应用软件. 进程:正在运行的程序,会在内存中分配空间. 线程:进程中的多条路径. 多线程是指有多条线程并发的执行. 并 ...

  6. Java多线程基础知识(一)

    Java多线程 一.Java线程模型 实现线程有三种方式:使用内核线程实现.使用用户线程实现和使用用户线程加轻量级进程混合实现.内核线程是直接由操作系统内核支持的线程,通过内核完成线程切换,内核通过操 ...

  7. Android多线程基础知识详解(傻瓜教程)

    线程的基本用法 Android中的多线程和Java中的多线程语法基本相同.定义一个新的线程首先需要新建一个类继承自Thread,然后重写父类方法run(),在run()方法中编写耗时逻辑即可.一般情况 ...

  8. Java程序设计 多线程 基础知识题

    2-1 以下哪个方法用于定义线程的执行体? ( ) (1分) A. start() B. init() C. run() D. ynchronized() 2-2 以下哪个关键字可以用来为对象加互斥锁 ...

  9. linux多线程——基础知识+实现

    在Linux中利用C语言实现多线程.利用函数pthread_create().pthread_exit().pthread_join(). 一.pthread_create() #include &l ...

最新文章

  1. oracle full outer join,oracle 内连接(inner join)、外连接(outer join)、全连接(full join)...
  2. 机器学习(MACHINE LEARNING)MATLAB经济金融领域简单数学模型和分析
  3. mac全选文字的快捷键_在mac上写作必须知道的四组快捷键
  4. JQuery UI - resizable
  5. Duilib教程-简单介绍
  6. 20190720学习小结
  7. INCEPTION 编译过程报错 make[2]: * [sql/CMakeFiles/sql.dir/sql_yacc.cc.o] Error
  8. Atitit.md5 实现原理
  9. 自动化机器人 rpa_机器人过程自动化和机器人的出现
  10. 图书馆管理系统mysql的创建_简单的图书馆管理系统数据库设计
  11. 批处理Bat教程-第七章:常用实例 下
  12. Win10 时间与Internet时间同步超时
  13. Qt VTK软件开发问题学习记录
  14. Android 性能优化 (一)APK高效瘦身
  15. 政府信息化需求开启 OA办公系统平台化时代
  16. 服务器怎么防ddos攻击
  17. H3C HCL模拟器 MPLS ipv4/ipv6双栈实验
  18. echarts 树图属性设置
  19. DeFi之道访谈:如何参与Web3?哪些细分赛道值得关注?
  20. vue中读取文本文件内容_vue中读取本地文件

热门文章

  1. windows下连接db2数据库
  2. Eight Machine Learning JavaScript Frameworks to Explore
  3. Science上发表的超赞聚类算法
  4. 图的存储之链式前向星
  5. spring boot框架学习学前掌握之重要注解(2)-通过java的配置方式进行配置spring
  6. 前端常见算法的JS实现
  7. 关于两个php.ini的说明
  8. 交换机 BootROM 下的升级配置
  9. Java牛角尖【009】: 多线程中synchronized的锁定方式
  10. Spring事务隔离级别,事务传播行为