go并发之goroutine和channel,并发控制入门篇
并发的概念及其重要性
这段是简单科普,大佬可以跳过
并发:并发程序指同时进行多个任务的程序。在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。
----------本段引用内容源自《GO语言高级编程》
在早期,CPU都是以单核的形式顺序执行机器指令。Go语言的祖先C语言正是这种顺序编程语言的代表。顺序编程语言中的顺序是指:所有的指令都是以串行的方式执行,在相同的时刻有且仅有一个CPU在顺序执行程序的指令。
随着处理器技术的发展,单核时代以提升处理器频率来提高运行效率的方式遇到了瓶颈,目前各种主流的CPU频率基本被锁定在了3GHZ附近。单核CPU的发展的停滞,给多核CPU的发展带来了机遇。相应地,编程语言也开始逐步向并行化的方向发展。Go语言正是在多核和网络化的时代背景下诞生的原生支持并发的编程语言。
在聊并发之前,聊聊共享变量、线程、协程
- 如何在不同线程/协程 共享 变量/内存?
这里留给各位看官去自行查资料,即使我列出来也不如自己动手去查记忆深刻!
不想查也可以等我下一篇文章,更加详细解读线程、进程。
- 线程和协程概念?
线程:线程是操作系统能够进行运算调度的最小单位。一个进程可以包含多个线程,是进程中的实际运作单位。
协程:又称微线程。协程是一种用户态的轻量级线程。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。
- 为什么会诞生协程?
虽然多线程在前互联网世代已经足够使用,但是线程的局限性也比较明显
- 线程数量有限,一般不会很多
- 线程占据的资源通常比我们需要的多得多,造成浪费
每个系统级线程开辟都会占用空间,这个空间可能是MB级别,但是我们如果使用的线程只需要传递KB级别数据,那么线程看起来就会比较浪费,但是又不可避免。而且线程之间的切换也会占用一些额外开销。
为了解决上面的矛盾问题,协程诞生了:更小的资源开支,动态调配资源,比线程更轻量。
协程的一些优点:
- 因为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。
- 不需要多线程的锁机制,因为只有一个线程,也不存在同时写变量冲突,在协程中控制共享资源不加锁,只需要判断状态就好了,所以执行效率比多线程高很多。
在golang中,goroutine的创建消耗非常小,大约是KB级别。因此可以创建更多的协程,尤其是数量越多相对线程优势更加明显,而且goroutine可以动态伸缩,栈溢出风险也比线程更低。
golang的并发,goroutine的使用
var name = "yiyiyinhe"
func changeName() {
name = "change"
}
func sayHi() {
fmt.println("hi, ", name)
go changeName() // 协程
}
简单的协程就创建了,那么打印出来的结果可能是hi, yiyiyinhe也可能是hi, change。
如果想对某一代码块执行协程而不是某个方法,则使用下面方式
var name = "yiyiyinhe"
func sayHi() {
fmt.println("hi, ", name)
go func() { // 匿名函数执行协程
name = "change"
}
}
channel
golang对共享变量的口号
Do not communicate by sharing memory; instead, share memory by communicating.
不要通过共享内存来通信,而应通过通信来共享内存。
那么在协程中也需要进行通信,而golang使用的goroutine之间通信和同步的主要方法是channel。
什么是channel呢?
A channel is a communic ation mechanism that lets one goroutine send values to another goroutine. Each channel is a conduit for values of a particular type, called the channel’s element type.
channel是一种通信机制,它让一个goroutine向另一个goroutine发送值。每个通道都是特定类型(通道元素类型)值的管道。
简单来理解就是,channel是用于在goroutine中进行通信的管道,而且管道是有特定类型的。
创建的channel分为有缓存和无缓存两种,区别就是创建的时候是否分配大小
无缓存channel
var ch1 = make(chan int),未分配大小var ch2 = make(chan int, 0),分配大小为0也等同给于未分配大小
有缓存channel
var :ch3 = make(int, 3),分配大小为3的有缓存channel
在无缓存channel中,channel的发送操作总是在接收之前发生;简单理解就是,无缓存channel是一个管道必须从头flag<-true发送到尾部<-flag,而且尾部发生的时间一定是在头部发送之后。
为什么chennel可以这样呢?
因为channel有阻塞作用,必须接收了才能继续下去。
有缓存channel则不具备上述的特性,因为对于带缓冲的Channel,对于Channel的第 K 个接收完成操作发生在第 K+C 个发送操作完成之前,其中 C 是Channel的缓存大小。 如果将 C 设置为0自然就对应无缓存的Channel,也即使第K个接收完成在第K个发送完成之前。因为无缓存的Channel只能同步发1个,也就简化为前面无缓存Channel的规则:对于从无缓冲Channel进行的接收,发生在对该Channel进行的发送完成之前。
还是上面的例子,使用channel来演示一下
var name = "yiyi"
var flag = make(chan bool) // 创建了bool类型的channel
func changeName() {
name = "change"
flag <- true // 发送
}
func sayHi() {
go changeName() // 协程
<-flag // 接收
fmt.println("hi, ", name)
}
那么这个时候打印出来的就是一个固定的顺序,由于<-flag接收总是在发送之后执行,因此当flag <- true执行完之前name = "change"已经执行,打印结果一定是:hi, change
上面代码等同于下图所示
看完你可以收获什么?
- 简单了解并发,了解多线程简单的发展来历
- 简单了解线程,协程
- 为什么协程会诞生?
- goroutine的两种使用方式
- channel是什么?channel的两种分类;
- channel在goroutine中有什么作用?
写在最后
由于我刚开始写技术文章,很多东西不知道怎么写才能让大家都看懂,就像写线程协程的时候不知道要不要解释共享变量或者共享内存是什么,也不知道大家能不能知道多线程模式下线程之间通信有哪些方式,感觉都想写但是又觉得大家看文章标题应该是了解一些东西的,如果都写篇幅太长,不写又看不懂;就觉得比较矛盾吧,也希望大家能够给我提一些意见建议!
作者还在慢慢努力,尽量把文章写的通俗易懂,排版准确,抓住重点,把最好的内容展现给大家。
go并发之goroutine和channel,并发控制入门篇的更多相关文章
- Android开发之BUG专讲:入门篇(一)
前言: 本文作者:周才智 转载须注明作者与出处.违者必究. 原文地址:http://segmentfault.com/a/1190000004380690 话说诸葛亮是一个优秀的程序员,每个锦囊都是应 ...
- TODO:Go语言goroutine和channel使用
TODO:Go语言goroutine和channel使用 goroutine是Go语言中的轻量级线程实现,由Go语言运行时(runtime)管理.使用的时候在函数前面加"go"这个 ...
- goroutine 加 channel 代替递归调用,突破递归调用的层级限制
package main import ( "fmt" "github.com/davecgh/go-spew/spew" "github.com/B ...
- Go基础--goroutine和channel
goroutine 在go语言中,每一个并发的执行单元叫做一个goroutine 这里说到并发,所以先解释一下并发和并行的概念: 并发:逻辑上具备同时处理多个任务的能力 并行:物理上在同一时刻执行多个 ...
- goroutine和channel
近期在学习golang的goroutine和channel时候有一些疑惑: 带缓冲的channel和不带缓冲的channel有什么区别? goroutine和主进程的有哪些影响和关系? 多个gorou ...
- [转帖]go 的goroutine 以及 channel 的简介.
进程,线程的概念在操作系统的书上已经有详细的介绍.进程是内存资源管理和cpu调度的执行单元.为了有效利用多核处理器的优势,将进程进一步细分,允许一个进程里存在多个线程,这多个线程还是共享同一片内存空间 ...
- Go part 8 并发编程,goroutine, channel
并发 并发是指的多任务,并发编程含义比较广泛,包含多线程.多进程及分布式程序,这里记录的并发是属于多线程编程 Go 从语言层面上支持了并发的特性,通过 goroutine 来完成,goroutine ...
- Go开发[八]goroutine和channel
进程和线程 进程是程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位. 一个进程可以创 ...
- Go--关于 goroutine、channel
Go--关于 goroutine.channel goroutine 协程是一种轻量化的线程,由Go编译器进行优化. Go协程具有以下特点: 有独立的栈空间 共享程序堆中的空间 调度由用户控制 如果主 ...
随机推荐
- C# 9.0新特性详解系列之二:扩展方法GetEnumerator支持foreach循环
1.介绍 我们知道,我们要使一个类型支持foreach循环,就需要这个类型满足下面条件之一: 该类型实例如果实现了下列接口中的其中之一: System.Collections.IEnumerable ...
- 新鲜出炉!花了三天整理的JVM复习知识点,面试突击必备!
此次JVM知识点包含以下几个部分 1.类加载机制 2.jvm运行时数据区 3.java对象内存布局 4.jvm内存模型 5.垃圾回收机制 6.垃圾收集器 7.问题排查 一 类加载机制 主要说的部分是这 ...
- Camtasia对录制视频字幕编辑的教程
我们小时候会有这样的疑问,电视剧上的字幕是怎么做成的呢.字幕又是怎么不会从一幕到下一幕而产生不对应的呢.这就是影视的后期处理的结果了,利用视频的编辑软件,工作者们可以在特定的时间内加上相对应的台词,然 ...
- 使用CleanMyMac快速管理应用程序 优化Mac
CleanMyMac作为一款专业的苹果电脑清理软件,它不仅仅能单纯的卸载不用.少用的应用,同时还支持:1.清理应用程序的数据文件,将应用重置回初始状态,减少空间占用:2.自动检查应用更新,保持应用的最 ...
- Vegas的软对比具体如何设置
软对比是Vegas中比较常用的一个视频特效,通过这一特效可以让视频画面更加柔和.而对于新手用户来说,软对比显得有些陌生,不知道该如何使用. 本集主要为大家介绍:sony vegas的软对比. 在视频制 ...
- Meetings S 题解
题目描述 题目链接 有两个牛棚位于一维数轴上的点 \(0\) 和 \(L\) 处.同时有 \(N\) 头奶牛位于数轴上不同的位置(将牛棚和奶牛看作点).每头奶牛 \(i\) 初始时位于某个位置 \(x ...
- C++基础知识篇:C++ 基本语法
C++ 基本语法 C++ 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互.现在让我们简要地看一下什么是类.对象,方法.即时变量. 对象 - 对象具有状态和行为.例如:一只狗的状态 - 颜 ...
- TeXstudio 2020显示行号(与之前的版本位置不太一样)
- 小样本学习最新综述 A Survey on Few-shot Learning | Introduction and Overview
目录 01 Introduction Bridging this gap between AI and humans is an important direction. FSL can also h ...
- UnityEditorWindow做一个TimeLine的滑动块
UnityEditorWindow做一个TimeLine的滑动块 最近在做一个基于TimeLine的动画编辑器,在制作TineLine滑动条时遇到问题,网上查了好久,试了好多GUI组件都不满意.最后在 ...