array(2) { ["docs"]=> array(10) { [0]=> array(10) { ["id"]=> string(3) "428" ["text"]=> string(77) "Visual Studio 2017 单独启动MSDN帮助(Microsoft Help Viewer)的方法" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(8) "DonetRen" ["tagsname"]=> string(55) "Visual Studio 2017|MSDN帮助|C#程序|.NET|Help Viewer" ["tagsid"]=> string(23) "[401,402,403,"300",404]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400964" ["_id"]=> string(3) "428" } [1]=> array(10) { ["id"]=> string(3) "427" ["text"]=> string(42) "npm -v;报错 cannot find module "wrapp"" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "zzty" ["tagsname"]=> string(50) "node.js|npm|cannot find module "wrapp“|node" ["tagsid"]=> string(19) "[398,"239",399,400]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400760" ["_id"]=> string(3) "427" } [2]=> array(10) { ["id"]=> string(3) "426" ["text"]=> string(54) "说说css中pt、px、em、rem都扮演了什么角色" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(12) "zhengqiaoyin" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511400640" ["_id"]=> string(3) "426" } [3]=> array(10) { ["id"]=> string(3) "425" ["text"]=> string(83) "深入学习JS执行--创建执行上下文(变量对象,作用域链,this)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "Ry-yuan" ["tagsname"]=> string(33) "Javascript|Javascript执行过程" ["tagsid"]=> string(13) "["169","191"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511399901" ["_id"]=> string(3) "425" } [4]=> array(10) { ["id"]=> string(3) "424" ["text"]=> string(30) "C# 排序技术研究与对比" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "vveiliang" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(8) ".Net Dev" ["catesid"]=> string(5) "[199]" ["createtime"]=> string(10) "1511399150" ["_id"]=> string(3) "424" } [5]=> array(10) { ["id"]=> string(3) "423" ["text"]=> string(72) "【算法】小白的算法笔记:快速排序算法的编码和优化" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(9) "penghuwan" ["tagsname"]=> string(6) "算法" ["tagsid"]=> string(7) "["344"]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511398109" ["_id"]=> string(3) "423" } [6]=> array(10) { ["id"]=> string(3) "422" ["text"]=> string(64) "JavaScript数据可视化编程学习(二)Flotr2,雷达图" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "chengxs" ["tagsname"]=> string(28) "数据可视化|前端学习" ["tagsid"]=> string(9) "[396,397]" ["catesname"]=> string(18) "前端基本知识" ["catesid"]=> string(5) "[198]" ["createtime"]=> string(10) "1511397800" ["_id"]=> string(3) "422" } [7]=> array(10) { ["id"]=> string(3) "421" ["text"]=> string(36) "C#表达式目录树(Expression)" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(4) "wwym" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(4) ".NET" ["catesid"]=> string(7) "["119"]" ["createtime"]=> string(10) "1511397474" ["_id"]=> string(3) "421" } [8]=> array(10) { ["id"]=> string(3) "420" ["text"]=> string(47) "数据结构 队列_队列实例:事件处理" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(7) "idreamo" ["tagsname"]=> string(40) "C语言|数据结构|队列|事件处理" ["tagsid"]=> string(23) "["246","247","248",395]" ["catesname"]=> string(12) "数据结构" ["catesid"]=> string(7) "["133"]" ["createtime"]=> string(10) "1511397279" ["_id"]=> string(3) "420" } [9]=> array(10) { ["id"]=> string(3) "419" ["text"]=> string(47) "久等了,博客园官方Android客户端发布" ["intro"]=> string(288) "目录 ECharts 异步加载 ECharts 数据可视化在过去几年中取得了巨大进展。开发人员对可视化产品的期望不再是简单的图表创建工具,而是在交互、性能、数据处理等方面有更高的要求。 chart.setOption({ color: [ " ["username"]=> string(3) "cmt" ["tagsname"]=> string(0) "" ["tagsid"]=> string(2) "[]" ["catesname"]=> string(0) "" ["catesid"]=> string(2) "[]" ["createtime"]=> string(10) "1511396549" ["_id"]=> string(3) "419" } } ["count"]=> int(200) } 222 Go并发编程-并发与并行 - 爱码网

一、前言

很多人会把并发与并行的概念弄混,有时候说并发有时候说并行,那么两者究竟有啥区别那,本节我们就来澄清下两者概念。

二、并发与并行

首先我们先看下什么是进程,比如你打开的微信app就是一个进程、打开的手淘App、记事本程序就是一个进程,在高级编程语言中你启动main函数运行后其实也启动了一个进程。

进程(Process)是计算机中的程序在某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,也就是说操作系统是以进程为单位进行资源分配的,但是 CPU 这个资源却比较特殊,CPU 的分配是以线程为单位的,这是因为具体占用 CPU 运行的是进程中的线程。一个进程中至少有一个线程,比如启动main函数运行的时候,main函数所在线程就是该进程的主线程,在go中main函数所在线程的生命周期等于进程的生命周期,当main函数所在线程运行结束后,进程就退出了。Go并发编程-并发与并行

如上图进程中包含进程控制块(PCB)和用户地址空间和很多线程:

  • 其中PCB用来保存进程的控制信息,比如每个pc上全局唯一的进程编号,进程的上下信息(当进程执行上下文切换时候要保存当前进程的上下文信息),控制信息(比如用来管理调度的进程的状态、进程间通信的信号量或消息队列信息、cpu资源的使用情况等)

  • 用户地址空间则用来保存进程运行时需要的代码和数据等信息。

  • 每个进程中可以有多个线程,每个线程有自己的用户栈资源,用于存储该线程的局部变量,这些局部变量是该线程私有的,其它线程是访问不了的,另外栈还用来存在当前线程的函数调用栈帧信息,用户栈用来存放用户程序执行的一些信息,系统栈用来存放native调用的执行信息。

并发是指同一个时间段内多个任务同时交叉执行,并且都没有执行结束,而并行是说在单位时间内多个任务同时在执行,并发任务强调在一个时间段内同时执行,而一个时间段有多个单位时间累积而成,所以说并发的多个任务在单位时间内不一定同时在执行。

在单个cpu的时代多个任务同时运行都是并发,这是因为cpu同时只能执行一个任务,单个cpu时代多任务是共享一个cpu的,当一个任务占用cpu运行时候,其它任务就会被挂起,当占用cpu的任务时间片用完后,会把cpu让给其它任务来使用,所以在单cpu时代多线程编程是意义不大,并且线程间频繁的上下文切换还会带来开销。

如下图单个cpu上运行两个线程,可知线程A和B是轮流使用cpu进行任务处理的,也就是同时CPU只在执行一个线程上面的任务,当前线程A的时间片用完后会进行线程上下文切换,也就是保存当前线程的执行线程,然后切换线程B占用cpu运行任务,线程A和线程B走走停停、交叉运行的,我们就说线程A和线程B是并发运行的:

Go并发编程-并发与并行

如下图双cpu时候,线程A和线程B各自在自己的CPU上执行任务,实现了真正的并行运行。

Go并发编程-并发与并行

而在多线程编程实践中线程的个数往往多于CPU的个数,所以平时都是称多线程并发编程而不是多线程并行编程。

三、为什么要多线程并发编程

随着多核CPU时代的到来,打破了单核CPU对多线程效能的限制,多个CPU意味着每个线程可以使用自己的CPU运行,这减少了线程上下文切换的开销,并且随着对应用系统性能和吞吐量的要求提高,还有海量数据处理和请求的要求,都对高并发编程有着迫切的需求。

四、总结

并发强调多个任务在一个时间段内走走停停,交叉运行,并不要求多个任务在单位时间内同时运行,例如在单cpu上运行多个任务或者在任务数大于cpu个数时候使用分时复用cpu策略运行任务就是并发运行;而并行则强调多个任务同时运行。

相关文章: