一。并发&并行

一个应用程序  ---> 一个进程 ---> 运行在自己内存地址空间里的独立执行体 ---> 同一个内存地址空间的一起工作的多个线程

一个并发程序 ---> 多个线程来执行任务 ---> 某个时间点同时运行在多核或者多处理器 ---> 并发&并行

---> 某个时间点同时运行在单个处理器     --\---> 并发&不并行

并行是一种通过使用多处理器以提高速度的能力。所以并发程序可以是并行的,也可以不是。

公认的,使用多线程的应用难以做到准确,最主要的问题是内存中的数据共享,它们会被多线程以无法预知的方式进行操作,导致一些无法重现或者随机的结果(称作 竞态

并发方式:

1.确定性的(明确定义排序)

2.非确定性的(加锁/互斥从而未定义排序)---> 竞态

不要使用全局变量或者共享内存,它们会给你的代码在并发运算的时候带来危险。

解决之道:

1.同步不同的线程,对数据加锁,这样同时就只有一个线程可以变更数据

2.有个被称作 Communicating Sequential Processes(顺序通信处理)(CSP, C. Hoare 发明的)

3.还有一个叫做 message passing-model(消息传递)(已经运用在了其他语言中,比如 Erlang)

二。go的协程

在 Go 中,应用程序并发处理的部分被称作 goroutines(协程)

协程 ---> 工作在相同的地址空间 ---> 共享内存的方式一定是同步的;这个可以使用 sync 包来实现(不推荐)

---> 使用 channels 来同步协程

特点:

1.使用少量的内存和资源:使用 4K 的栈内存就可以在堆中创建它们

2.对栈进行了分割,从而动态的增加(或缩减)内存的使用;栈的管理是自动的,但不是由垃圾回收器管理的,而是在协程退出后自动释放

3.协程可以运行在多个操作系统线程之间,也可以运行在线程之内

4.使用少量的操作系统线程就能拥有任意多个提供服务的协程,而且 Go 运行时可以聪明的意识到哪些协程被阻塞了,暂时搁置它们并处理其他协程

5.存在两种并发方式:确定性的(明确定义排序)和非确定性的(加锁/互斥从而未定义排序)。Go 的协程和通道理所当然的支持确定性的并发方式(例如通道具有一个 sender 和一个 receiver)

实现形式:

关键字 go 调用 ---> 一个函数或者方法 ---> 在当前的计算过程中开始一个同时进行的函数 ---> 在相同的地址空间中并且分配了独立的栈(栈分割)

协程的栈会根据需要进行伸缩,不出现栈溢出;开发者不需要关心栈的大小。当协程结束的时候,它会静默退出:用来启动这个协程的函数不会得到任何的返回值

三。go协程并行:

Go 默认没有并行指令,只有一个独立的核心或处理器被专门用于 Go 程序,不论它启动了多少个协程;所以这些协程是并发运行的,但他们不是并行运行的:同一时间只有一个协程会处在运行状态

在 gc 编译器下(6g 或者 8g)你必须设置 GOMAXPROCS 为一个大于默认值 1 的数值来允许运行时支持使用多于 1 个的操作系统线程,所有的协程都会共享同一个线程除非将 GOMAXPROCS 设置为一个大于 1 的数。当 GOMAXPROCS 大于 1 时,会有一个线程池管理许多的线程。通过 gccgo 编译器 GOMAXPROCS 有效的与运行中的协程数量相等。假设 n 是机器上处理器或者核心的数量。如果你设置环境变量 GOMAXPROCS>=n,或者执行 runtime.GOMAXPROCS(n),接下来协程会被分割(分散)到 n 个处理器上。更多的处理器并不意味着性能的线性提升。有这样一个经验法则,对于 n 个核心的情况设置 GOMAXPROCS 为 n-1 以获得最佳性能,也同样需要遵守这条规则:协程的数量 > 1 + GOMAXPROCS > 1。

所以如果在某一时间只有一个协程在执行,不要设置 GOMAXPROCS!

还有一些通过实验观察到的现象:在一台 1 颗 CPU 的笔记本电脑上,增加 GOMAXPROCS 到 9 会带来性能提升。在一台 32 核的机器上,设置 GOMAXPROCS=8 会达到最好的性能,在测试环境中,更高的数值无法提升性能。如果设置一个很大的 GOMAXPROCS 只会带来轻微的性能下降;设置 GOMAXPROCS=100,使用 top 命令和 H 选项查看到只有 7 个活动的线程。

增加 GOMAXPROCS 的数值对程序进行并发计算是有好处的;

总结:GOMAXPROCS 等同于(并发的)线程数量,在一台核心数多于1个的机器上,会尽可能有等同于核心数的线程在并行运行。

最新文章

  1. 查看java源码显示source not found
  2. robotframework接口测试初探3
  3. maven加载本地lib下的jar包
  4. mysql 命令行
  5. 【云计算】docker的小知识,帮你更深入理解容器技术
  6. 使用Moses中tokenizer.perl无法正常工作:纠结的"<" 和">"(已解决)
  7. RAC 环境下修改归档模式
  8. Linux makefile教程之make运行八[转]
  9. 创新高性能移动 UI 框架-Canvas UI 框架
  10. LaTex希腊字母
  11. SQLServer 扫盲
  12. VR全景智慧城市搭建掀起实体市场潮流
  13. 分布式进阶(一)Windows 7下硬盘安装Ubuntu 14.04图文教程
  14. python 关于操作文件的相关模块(os,sys,shutil,subprocess,configparser)
  15. 部分视图 - partial
  16. [GNU] 喝一杯咖啡, 写一写 Makefile
  17. redux模块化demo
  18. HDU 1171 01背包
  19. Linux错误代码含义
  20. v891 安卓平板的root

热门文章

  1. 交叉编译问题记录-嵌入式环境下 GDB 的使用方法
  2. 搭建前端监控系统(二)JS错误监控篇
  3. React native 环境搭建遇到问题解决(android)
  4. IDEA出现Cannot resolve symbol "xxx"(无法解析符号)
  5. Mybatis事务管理
  6. 微信服务号获取openid方法
  7. canvas-3linearGradient.html
  8. blfs(systemv版本)学习笔记-编译安装i3-wm平铺式窗口管理器
  9. HTML5本地存储localStorage与sessionStorage详解
  10. thymeleaf-extras-db 0.0.1发布,select标签加载数据的新姿势