关于并行开发的一些概念整理【并发编程系列_1】

关于,并行,开发,一些,概念,整理,并发,编程,系列 · 浏览次数 : 324

小编点评

**主线程** * 主线程是程序开始时就执行的进程。 * 当前线程关闭掉时,也会停止执行。 * 线程池中的每个线程都在执行 while(true) 的循环。 **线程池** * 线程池中的每个线程都在执行 while(true) 的循环。 * 当线程池满的时候,也会按照工作项在队列里的顺序 FIFO(先进先出)取出并执行。 *全局队列是共享资源,所以内部会有锁的概念。 **其他** * **同步编程**:它和单线程的效果类似,进程之间的关系不是相互排斥临界资源的关系,而是相互依赖的关系。 * **异步编程**:它基于异步事件,而不是异步操作中的异步操作,异步事件可以在任何时间发生,并且可以发生多次。 * **函数式编程**:大多数并发编程,其本质都是函数式的,函数式编程有两个原则,一个是简洁,有非常清晰的输入和输出,而且尽可能的避免全局或者共享变量。

正文

〇、前言

想很好的理解并行开发,需要了解的知识还是有很多的,下边就简单罗列几个概念。

一、相关概念简介

1、任务管理器中的 基准速度、插槽、内核、逻辑处理器

基准速度

  就是处理器晶体管打开和关闭的速率,也就是 CPU 运作的参考速度。听起来像是速度越快越好,但是也有一定的局限性,也需要合适体量的内核才能发挥效用,另外速度的提高也伴随着更高的能耗。

插槽

  指的是主机支持插入几个物理 CPU。

内核

  又叫物理内核,一个物理 CPU 可以包含多个物理内核。

逻辑处理器

  即逻辑 CPU,一个物理内核可以包含多个逻辑 CPU。计算机设备管理器中显示的处理器个数对应的就是逻辑处理器的个数。

举个例子:

  如下图,因为只有一个插槽,所以就只能装机一个物理 CPU,然后一个物理 CPU 包含 6 个物理内核,一个内核中包含两个逻辑处理器,即 1 x 6 x 2 = 12。

  

2、进程与线程

进程-Process

  指的是程序的一次执行的过程,是一个动态概念,也是程序在执行过程中分配和管理资源的基本单位。

线程

  是 CPU 调度和分派的基本单位,它可与同属一个进程的其他的线程共享进程所拥有的全部资源。每个进程都会有一个主线程(Main Thread)。

进程、线程、逻辑处理器之间的关系

  线程是进程的一部分,一个线程只能属于一个进程,而一个进程有一个到多个线程。

  进程和线程的根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位。

  逻辑处理器的个数,代表计算机同时能有同样个数的线程在工作。

3、硬件线程和软件线程

硬件线程也叫逻辑处理器或逻辑内核,同样的,一个物理内核就可以包含多个硬件线程。

软件线程(Software Thread)就是我们常提到的线程。

Windows 将每一个硬件线程识别为一个可调度的逻辑处理器,每一个逻辑处理器可以运行软件线程代码,运行多个软件线程的进程可以充分发挥硬件线程和物理内核的优势,并行地运行指令。

Windows 会给每一个可用的硬件线程分配一块块的处理时间,并通过这种方式运行上百个千个软件线程。

4、并行与并发

并发:关键是你处理多个任务的能力一定要同时

并行:关键是你有同时处理多个任务的能力。

所以区别它们最关键的点就是:是否是“同时”。可见,能够“同时”的并行,效率相对更高。

举例:假如你吃饭吃到一半,电话来了,然后:

  • 你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。(按顺序一个一个处理)
  • 你停了下来接了电话,接完后继续吃饭,这说明你支持并发。(都可以做,但当时只能做一件事)
  • 你一边打电话一边吃饭,这说明你支持并行。(可以同时做多件事)

5、单线程与多线程

单线程

  就是一个进程只有一个线程。程序执行时,所走的程序路径按照连续顺序排下来,前面的必须处理好,后面的才会执行。

多线程

  就是一个进程有多个线程。在程序执行时,所有线程会交替执行。后面的线程不用等待前面的线程处理完毕。

多线程根据并行和并发又有不同的情况。

  • 在并发时,多个线程会抢占cpu资源执行一块逻辑,没有抢到cpu资源的就会进入等待状态,等cpu空闲后继续抢占资源。这就像一个车间只有一台机器,所有的工人都有相同的任务,他们都要使用这台机器,抢到的工人就执行任务,没有抢到的工人就等待任务执行完毕后,继续抢这台机器。
  • 在并行时,多个线程会同时执行一块代码逻辑。就像一个车间有四台机器,四个工人分别使用四台机器,同时执行任务,不用等待其它工人任务执行完毕。

使用场景的区别:

  • 单线程:当有三件事要处理,乙 需要在 甲 之后处理,同时 丙 需要在 乙 之后,这种事件有特定的先后顺序(甲-->乙-->丙)。
  • 多线程:需处理的多件事互相独立。例如下载大文件时的进度条和实际下载进度,就需要一边显示进度一边进行下载。

6、上下文切换

CPU 通过时间片轮转算法来循环执行线程任务,每次执行并不是直接将任务完成。这种切换用时很短,从而使各个程序的运行从表面上看是同时进行的。切换时会保存之前的线程任务状态,当切换到该线程任务的时候,会重新加载该线程的任务状态。而这个从保存到加载的过程称之为上下文切换。

比如我们拿了两本书,一本中英文词典,一本英文书,在读英文书时发现某个单词不认识,于是便打开中英文词典看单词的汉译,但是放下英文书之前,大脑必须记下这本书读到了多少页的多少行,等查询完单词之后,能够继续读这本书。但这样的切换是会影响读书效率的,同样上下文切换也会影响多线程的执行速度。

由于线程的状态保存和加载都是耗时的,所以在执行串行化代码时,多线程相比单线程效率低。

7、异步、同步、响应、函数式编程

异步编程

  是并发的一种形式,老式的异步编程采用回调的机制,以避免创建不必要的线程。异步编程的核心概念是异步操作,即启动的操作会在一定时间后才能完成,这个操作正在执行,却并不会阻塞原来的线程,启动了这个操作的线程还可以继续执行其他任务,等操作完成时,它会调用回调函数,已让程序知道操作已经结束了。

同步编程

  它和单线程的效果类似,进程之间的关系不是相互排斥临界资源的关系,而是相互依赖的关系。即前一个进程的输出作为后一个进程的输入,当第一个进程没有输出时第二个进程必须等待。具有同步关系的一组并发进程相互发送的信息称为消息或事件。其中并发又有伪并发和真并发,伪并发是指单核处理器的并发,真并发是指多核处理器的并发。

响应编程

  是另一种形式的并发编程,它基于异步事件,而不是异步编程中的异步操作,异步操作有一个开始执行的概念,但是异步事件可以在任何时间发生,并且可以发生多次,大概类似于用户响应事件的概念。它是一种声明式的编程模式,程序在该模式中对事件做出与之对应的响应。

函数式编程

  大多数并发编程,其本质都是函数式的,函数式编程有两个原则,一个是简洁,有非常清晰的输入和输出,而且尽可能的避免全局或者共享变量。另一个原则就是不变性,指一段数据不能被修改,程序永远不需要对这些数据进行同步,就是非常简单的输入数据,输出数据。

8、主线程、前台线程、后台线程 --20230714

当一个程序启动时,就有一个进程被操作系统(OS)创建,与此同时一个线程也立刻运行,该线程通常叫做程序的主线程(Main Thread),因为它是程序开始时就执行的,如果你需要再创建线程,那么创建的线程就是这个主线程的子线程。 

上述中新建的子线程可以是前台线程,也可以是后台线程,他们具有以下特点:

  • 前台线程必须全部执行完,即使主线程关闭掉,这时进程仍然存活。
  • 后台线程在未执行完成时,如果前台线程关掉,则后台线程也会停掉,且不抛出异常。

也就是说,前台线程与后台线程唯一的区别是后台线程不会阻止进程终止,可以在任何时候将前台线程修改为后台线程

所以,只有在确认线程被系统随意终止没有不利影响时,才应该使用后台线程。如果线程正在执行必须完成的敏感操作或事务操作,或者需要控制关闭线程的方式以便释放重要资源,则使用前台线程。

9、线程池的全局队列、本地队列--20230720

对于线程池而言,并非是一个工作项在加入时直接交给线程去执行,而是直接放到一个队列系统中,其中的队列总共分两种,针对 全部线程全局队列针对某一线程本地队列。线程池中的每一个线程都在执行 while(true) 的循环,从这个队列系统中领取并执行任务。

对于大多数情况下,我们都是在线程池外将任务添加到线程池中。那如何将任务项直接加到某一线程的本地队列呐?下面给出答案:

  • 在 ThreadPool.QueueUserWorkItem 的重载方法 ThreadPool.QueueUserWorkItem<TState>(Action<TState> callBack, TState state, bool preferLocal) 里有一个 preferLocal 参数。
  • 调用不带 preferLocal 参数的 ThreadPool.QueueUserWorkItem 方法重载,任务会被放到全局队列。
  • 当 preferLocal 为 true 的时候,如果调用 ThreadPool.QueueUserWorkItem 代码的线程正好是个线程池里的某个线程,则该任务就会进入该线程的本地队列中。
  • 在线程池外的线程中调用,不管 preferLocal 传的是什么,任务都会被放到全局队列。

线程池中有空闲的工作线程时,就会按照工作项在队列里的顺序 FIFO(先进先出)取出并执行。

全局队列是共享资源,所以内部会有锁的概念。当业务比较复杂时,全局队列操作频繁,就会导致整体性能下降。

详情可参考:https://www.cnblogs.com/eventhorizon/p/15316955.html

10、、、

部分参考:并行编程相关概念  C#并发编程相关名词解释  单线程和多线程?  异步,多线程和并行的区别? 并发与并行的区别是什么? 

注:个人整理,难免有疏漏,请大方的指正或补充,博主也会第一时间进行修改或补充。后续如果博主发现有需要补充的也会持续更新。

与关于并行开发的一些概念整理【并发编程系列_1】相似的内容:

关于并行开发的一些概念整理【并发编程系列_1】

想很好的理解并行开发,需要了解的知识还是有很多的,下边就简单罗列几个概念。(纯文本)

《Flask Web 开发指南 pt.2》

哈喽大家好,我是咸鱼 在《Flask Web 开发指南 pt.1》中,咸鱼跟大家介绍了 Flask 的由来——诞生于一个愚人节玩笑,简单介绍了一些关于 Flask 的概念,并且编写了一个简单的 Flask 程序 在编写 Flask 程序的时候,你需要注意你的程序文件不要命名为 flask.py,建议

跳跃表数据结构与算法分析

目前市面上充斥着大量关于跳跃表结构与Redis的源码解析,但是经过长期观察后发现大都只是在停留在代码的表面,而没有系统性地介绍跳跃表的由来以及各种常量的由来。作为一种概率数据结构,理解各种常量的由来可以更好地进行变化并应用到高性能功能开发中。本文没有重复地以对现有优秀实现进行代码分析,而是通过对跳跃表进行了系统性地介绍与形式化分析,并给出了在特定场景下的跳跃表扩展方式,方便读者更好地理解跳跃表数据

基于Web3.0的区块链图片上传

开始前,我们先简单了解一下基本的概念,我大致归纳为以下几个点 什么是Web3.0,和区块链又有什么关系?(上回的文章不就派上用场了) 需求:开发一个基于Python的Web 3.0图片上传系统。这个系统将允许用户上传图片,并将图片存储在去中心化的网络上,同时记录交易信息在区块链上。 本就是写着玩的,

【专项测试系列】-缓存击穿、穿透、雪崩专项测试

作者:刘须华 一、背景概述: R2M 缓存的使用,极大的提升了应用程序的性能和效率,特别是数据查询方面。而缓存最常见的问题是缓存穿透、击穿和雪崩,在高并发下这三种情况都会有大量请求落到数据库,导致数据库资源占满,引起数据库故障。平时对缓存测试时除了关注增删修改查询等基本功能,应该要重点关注缓存穿透、

关于cockpit的学习

# 关于cockpit的学习 ## 背景 ``` 使用node-exporter 可以监控很多资源使用情况 但是这个需要搭建一套prometheus和grafana的工具 并且每个机器都需要安装一套node-exporter的进行数据dump cockpit 是红帽开发的一套监控组件, 可以监控网络

聊聊JDK1.0到JDK20的那些事儿

最近小组在开展读书角活动,我们小组选的是《深入理解JVM虚拟机》,相信这本书对于各位程序猿们都不陌生,我也是之前在学校准备面试期间大致读过一遍,emm时隔多日,对里面的知识也就模糊了。这次开始的时候从前面的JDK发展史和JVM虚拟机家族着手,之前都是粗略读过,这次通过查阅相关资料并收集在每一个JDK版本演化期间所发生的的一些趣闻,发现还是比较有意思的,以下是关于有关JDK发展史的总结分享。

[转帖]wiki Rust

Rust[编辑] 维基百科,自由的百科全书 跳到导航跳到搜索 此条目介绍的是由Mozilla主导开发的编程语言。关于“rust”在英文中的本意,请见“铁锈”。关于由Facepunch工作室所开发的一款游戏,请见“腐蚀 (游戏)”。 Rust 编程范型 编译语言、并发计算、函数式、指令式、面向对象、结

如何找到并快速上手一个开源项目

以前有写过两篇文章来简单聊过如何做开源的事情,最近我自己组了一个社区里面也有不少朋友对开源感兴趣,于是我便根据自己的经验系统的梳理了一些关于开源的事情。 新手如何快速参与开源项目 手把手教你为开源项目贡献代码 有兴趣的可以先看看之前这两篇。 如何找到自己感兴趣的开源项目 首先第一步先想清楚自己搞

分拣平台API安全治理实战 | 京东物流技术团队

导读 本文主要基于京东物流的分拣业务平台在生产环境遇到的一些安全类问题,进行定位并采取合适的解决方案进行安全治理,引出对行业内不同业务领域、不同类型系统的安全治理方案的探究,最后笔者也基于自己在金融领域的经验进行了关于API网关治理方案的分享。 写在前面 随着互联网应用的多元化、复杂化、服务化成为显