golang 并发

Golang 并发编程指南 简单调度图如上,有关于 P 再多个 M 中切换,公共 goroutine 队列,M 从线程缓存中创建等步骤没有体现,复杂过程可以参考文章简单了解。我们可以再每个 CPU 上进行循环无关的迭代计算,我们仅需要创建完所有的 goroutine 后,从 channel 中读取结束信号进行计数即可。这东西可以并发读,不可以并发读写/并发写写,不过现在即便场景是读多写少也很少用到这,一般集群环境都得分布式锁了。关系如图,灰色的 G 则是暂时还未运行的,处于就绪态,等待被调度,这个队列被 P 维护。 阅读详情

1、并发和并行

go语言协程依赖于线程,即使处理器运行的是统一线程,在线程内部go语言调度器也会切换多个协程执行,这个时候协程是并发的。如果多个协程被分配给了不同的线程,这些线程被不同的CPU核心处理,协程就是并行处理的。
故多核处理场景下,go语言的协程是并发

并发
在这里插入图片描述
并行
在这里插入图片描述

2、线程和协程的区别

协程是轻量级的线程

1、调度方式
协程是用户态的,协程和线程的对应关系是M:N。Go语言调度器可以将多个协程调度到同一个线程中,一个协程也可能切换到多个协程中执行
2、上线文切换速度
协程的速度要快于线程,是因为协程切换不用经过操作系统用户态和内核太的切换,并且协程切换的时候保留的寄存器要少于线程,线程切换大约需要1~2微秒,协程约为0.2微秒
3、调度策略
线程的调度大多数时间是抢占式的,操作系统调度器为了均衡每个线程的执行周期,会定时发出中断信号轻质执行线程上下文切换。而Go语言中的协程一般情况下是协作式调度,当一个协程处理完自己的任务后,可以主动将执行权限让给其他协程。这意味着协程可以更好的在规定时间内完成自己的工作,不会被轻易抢占。当一个协程运行了过长的时间,Go语言调度器才会抢占其执行
4、栈大小
线程的栈大小为2MB(避免栈一处),协程的栈默认为2KB。同时协程的栈在运行的时候是不能更改的,运行时会动态检测栈大小,动态扩容

3、golang 并发实现

goroutine 不是os线程、不是绿色线程(由语言运行时管理的线程),是协程。协程是一种非抢占式的简单并发子goroutine(函数、闭包或方法),也就是说,它们不能被中断。取而代之的是,协程有多个点,允许暂停或重新进入 —Go语言并发之道

  • goroutine是go的并发体
  • channels是goroutine的通信机制(实际就是发送数据)

基础知识

goroutine

goroutine是一种轻量级的实现,可以在单个进程中执行成千上万的并发任务,是go语言并发设计的核心.
将关键字go放在一个函数的前面,这个函数执行时就会成为一个独立的并发线程,这线程就被称为goroutine

channel 通道

通道(chan)是一种特殊的类型,是一种引用类型。
主要分类有单向通道、无缓冲的通道、带缓冲的通道
主要作用是同步信号(shutdown/close/finish) 消息传递(queue/stream) 互斥(mutex)

//go中对chan的定义   /runtime/chan.go
type hchan struct {
	qcount   uint           // total data in the queue    数据总量
	dataqsiz uint           // size of the circular queue
	buf      unsafe.Pointer // points to an array of dataqsiz elements
	elemsize uint16
	closed   uint32      //标记channel已经关闭
	elemtype *_type // element type
	sendx    uint   // send index
	recvx    uint   // receive index
	recvq    waitq  // list of recv waiters    和ring buffer相关
	sendq    waitq  // list of send waiters    和ring buffer相关

	// lock protects all fields in hchan, as well as several
	// fields in sudogs blocked on this channel.
	//
	// Do not change another G's status while holding this lock
	// (in particular, do not ready a G), as this can deadlock
	// with stack shrinking.
	lock mutex    //保护所有数据结构,但在某些quick path场景下不必加锁
}

type waitq struct {
	first *sudog
	last  *sudog     //sudog dequeue中等待的goroutine以及他的数据存储
}

底层原理参考

  • 任何时间只能有一个goroutine访问chan
  • chan 里面的数据满足FIFO规则
//声明通道
var 通道变量  chan  通道类型
//创建通道
通道实例  :=  make(chan 通道类型)
//给通道发送数据
通道变量  <-值
//读取通道数据
data, ok := <-通道变量
defer关键字

注意:defer会对表达式进行提前求值

go调度模型

go调度模型

在这里插入图片描述
G:goroutine
M:系统线程 -> 执行代码的实体
P:Processor调度实体

实现方式

syn包

进行多个任务的同步,主要操作有Add()、Done()、Wait()等操作

  • 互斥锁和读写锁

互斥锁 sync.Mutex:[互斥锁原理] (https://www.jb51.net/article/258684.htm)一个goroutine独占资源 互斥性、公平调度,饥饿处理
读写锁 sync.RWMutex:不可递归调用,读写互斥,多读之间并发

使用注意事项:

1、配套使用Lock、UnLock
2、运行时离开当前逻辑就释放锁
3、锁的粒度越小越好,加锁后尽快释放锁
4、没有特殊原因,尽量不要defer释放锁
5、RWMutex的读锁不要嵌套使用

  • List item
  • cond

sync.Cond 主要用于goroutine之间的协作,主要有三个函数Broadcast() , Signal(), Wait(), 一个成员变量,L Lock
Broadcast() :唤醒在本cond上等待的所有的goroutine
Signal():选择一个goroutine进行唤醒
Wait():让goroutine进行等待

  • once

sync.Once 中有一个Do()方法,无论是否更换Do()里面的东西,这个方法只会执行一次

func main() {
	var count int
	increment := func() {
		count++
	}

	var once sync.Once
	var increments sync.WaitGroup
	increments.Add(100)
	for i:=0;i<100;i++{
		go func() {
			defer increments.Done()
			once.Do(increment)
		}()
	}

	increments.Wait()
	fmt.Printf("count is %d\n", count)
}
//最终输出为 1
  • 池

池(pool)是Pool模式的并发安全实现,需要参照pool设计模式

channel
select 语句
GOMAXPROCS控制
runtime.GOMAXPROCS(runtime.NumCPU())   //充分利用cpu资源

Go语言的并发通过goroutine`实现。goroutine类似于线程,属于用户态的线程,我们可以根据需要创建成千上万个goroutine并发工作。goroutine是由Go语言的运行时(runtime)调度完成,而线程是由操作系统调度完成。

Go语言还提供channel在多个goroutine间进行通信。goroutine和channel是 Go 语言秉承的 CSP(Communicating Sequential Process)并发模式的重要实现基础。

经典例子分析

case1
func handler(){
	ch := make(chan string)
	go func() {
		time.Sleep(3*time.Second)
		ch <- "job result"
	}()

	select {
	case result := <- ch:
		fmt.Println(result)
	case <-time.After(time.Second):
		return
	}
}

上述代码会造成goroutine泄漏,原因在于channel没有缓存
可能造成goroutine泄漏的原因有:
1、channel没有缓存
2、select命中timeout逻辑
3、导致channel没有消费者
4、最终导致anonymous goroutine泄漏

case2

var mu sync.RWMutex
func main() {
	go A()
	time.Sleep(2*time.Second)

	fmt.Println("main call lock")
	mu.Lock()
	defer mu.Unlock()
}

func A()  {
	fmt.Println("A call rlock")
	mu.RLock()
	fmt.Println("A rlocked")
	defer mu.RUnlock()
	B()
}

func B(){
	time.Sleep(5*time.Second)
	C()
}

func C()  {
	fmt.Println("C call rlock")
	mu.RLock()
	fmt.Println("C rlocked")
	mu.RUnlock()
}

运行结果如下:
在这里插入图片描述

谨慎使用锁的递归调用,上面的还需再看一看

case3

go的map不可以并发

go内置map的几个要点:参考

  • hash算法:AES
  • 冲突解决:链地址法(和java类似) Python采用开放定址法
  • range go每次rangemap的时候顺序都会不同,因为go故意实现了random 【需要代码论据】
  • 装填因子 6.5
  • rehash 渐进式rehash (和redis类似)

Semaphore信号量

自旋锁

[go]golang snmp并发测试 没啥可说的,和ping差不多/*go routine版并发snmp测试*/ package main import ( "fmt" "github.com/k-sone/snmpgo" ) var fin chan string; //用于实现jionall func snmpr(host string){ snmp, err := snmpgo.NewSNMP(sn... 阅读详情

相关推荐

golang基础教程(十七)GO并发原理_go高并发原理视频教程

每个P中的Goroutine不同导致他们运行的效率和时间也不同,在一个有很多P和M的环境中,不能让一个P跑完自身的Goroutine就没事可做了,因为或许其他的P有很长的goroutine队列要跑,得需要均衡。我们现在的计算机语言,可以狭义的认为是一种“软件”,它们中所谓的“线程”,往往是用户态的线程,和操作系统本身内核态的线程(简称KSE),还是有区别的。CSP并发模型是在1970年左右提出的概念,属于比较新的概念,不同于传统的多线程通过共享内存来通信,CSP讲究的是“以通信的方式来共享内存”。

2401_87299687的博客 937

Golang 并发控制模型

Go语言的并发模型是CSP(通信顺序进程),提倡通过通信来进行内存共享,而不是通过共享内存来实现通信。控制并发有三种经典的方式,使用 channel 通知实现并发控制、使用 sync 包中的 WaitGroup 实现并发控制、使用 Context 上下文实现并发控制。

lp15929801907的博客 1846

golang学习笔记11——Go 语言的并发与同步实现详解

Go 语言的并发与同步机制使得开发者能够轻松地编写高效的并发程序。通过 goroutine 和 channel,开发者可以实现轻量级的并发编程,提高程序的性能和响应速度。同时,通过 mutex 和 wait group 等同步机制,开发者可以保护共享资源,确保程序的正确性。在实际开发中,开发者可以根据具体的需求选择合适的并发和同步机制,以实现高效、可靠的程序。**关注我看更多有意思的文章哦!**👉👉。

GoppViper的博客 2193

Golang:并发

进程定义:进程 是并发执行的程序中分配和管理资源的基本单位。线程定义:线程是进程的执行单元,是进行调度的实体,是比进程更小的独立运行单位。

qq_53158324的博客 580

Golang之并发的开发的详解

在Go语言中,有一个强大的特性——并发。通过并发,我们可以让程序同时执行多个任务,提高程序的效率和性能。 本文将为大家介绍Go语言中的并发特性,包括并发编程的基本概念、使用goroutine实现并发、使用channel进行通信等方面。同时,我们还将提供相关的学习代码和分析,帮助大家更好地理解并发编程的实现原理和技巧。

canduecho的专栏 1059

【Golang】Go语言中如何通过Goroutine快速实现高并发

并发编程是指在一个程序中同时运行多个任务,这些任务可以独立地执行,也可以相互协作。并发编程可以提高程序的执行效率,特别是在处理大量I/O操作或计算密集型任务时。 在Go语言中,并发编程主要通过goroutine和channel来实现。 Goroutine是Go语言独有的并发执行单元,它允许函数或方法并发执行,而无需手动管理线程。 Channel是Go语言中进行goroutine间通信和同步的主要机制。

景天科技苑 5万+

Go语言并发详解

文章目录一、Go语言并发简述(并发的优势)进程/线程并发/并行协程/线程Goroutine 介绍channel二、Go语言goroutine(轻量级线程)使用普通函数创建 goroutine1) 格式2) 例子使用匿名函数创建goroutine1) 使用匿名函数创建goroutine的格式2) 使用匿名函数创建goroutine的例子提示三、Go语言并发通信四、Go语言竞争状态简述Goroutine 7 (finished) created at: main.main() D:/code/src/m

qq_41854911的博客 1万+

go java 并发_golang百万并发-golang的并发性真的比Java高吗

使用了两种语言,但没有开发相同的业务。 然而,在目前的业务下,GO性能已经得到了具体的测试,而不会太担心GO性能,据说即将到来的GO1、5将再次提高性能太多。 其实还是很喜欢GO语言,简单,实用,并且适合大规模并发。 围棋学习阈值低于java。 如果担心gc影响实时,也可以申请大量内存做自己的内存管理。也许JavaGC更好,去不够。去并发比较好,Java达到同样效果,回调写死。真的很想知道,只是考...

weixin_26874745的博客 666

MAX30102心率血氧传感器

估算AC、DC值的方法如下:找两个波谷点,两个波谷点之间有一个波峰点,两个波谷点相连成一条直线,与Y轴平行的线穿过波峰点会与两个波谷点连接成的直线相交于一点,这个点就是DC点,DC点的Y轴对应值就是直流分量,AC分量的值为波峰点到DC点之间的差值。在医院测量中常用的一种血氧采集方式,如下图所示,光电传感器和光源分别置于手指的两侧,光源穿过手指被另一侧的光电二极管接收,根据光衰减量计算血氧浓度。那么,根据上面的Beer-Lambert 定理,针对测量的具体场景,测量过程的衰减为三层穿透物质衰减量的叠加。

qq_41861711的博客 1万+

省三医院新门诊大楼网络安全建设项目实施方案

为了响应国家建设数字医疗,构建医联网、医共体的号召,新门诊大楼现有计算机网络,实现各门诊室、药房、医学影像科室及后勤科室的终端数据互通。在互联网出口以三层模式部署两台防火墙,作为连接公网的出口设备;出于等保合规和自身业务安全的考虑,现需要该网络上通过网络安全设备实现安全建设。公网出口防火墙,配置攻击防御策略,防御互联网上的病毒进入内网。公网出口防火墙配置攻击防御策略,防御外网对内网的入侵行为。服务器取得边界防火墙,配置攻击防御策略,入侵防御策略。公网出口防火墙配置入侵防御策略,防御外网对内网发起的D。

m0_63645854的博客 2013

Golang并发(Go程、管道)

文章目录基础return、exit、goexit区别returnexitgoexit多go程通信(channel)管道的注意点管道nil管道死锁for range遍历管道判断管道是否已经关闭单向通道管道监听(select)管道总结 基础 并发:电脑同时听歌,看小说,打游戏。cpu根据时间片进行划分,交替执行这三个程序。我们可以感觉是同时产生的。 并行:多个cpu(多核)上述动作同时执行 C语言:,实现并发过程使用的是多线程(C++的最小资源单元) Golang:Golang中不是线程,而是Go程(goro

不诱于誉,不恐于诽,率道而行,端然正己。 1062

NumPy 与 Pandas 的详细应用(含实例)

本文系统介绍了Python数据分析中NumPy和Pandas两大核心库的应用。NumPy专注于高效数值计算,提供多维数组和向量化运算功能;Pandas则擅长结构化数据处理,支持数据清洗、分组统计等操作。文章详细讲解了库的安装、基础操作(数组/DataFrame创建、索引切片)、进阶功能(缺失值处理、分组聚合),并通过电商销售分析案例演示了实际应用场景。最后总结了二者的协同优势:NumPy负责底层数值计算,Pandas处理高级数据操作,配合使用可显著提升数据处理效率。建议读者从基础操作入手,结合实际案例练习,

weixin_42030577的博客 2297

go 比 java 并发高_golang百万并发-golang的并发性真的比Java高吗

使用了两种语言,但没有开发相同的业务。 然而,在目前的业务下,GO性能已经得到了具体的测试,而不会太担心GO性能,据说即将到来的GO1、5将再次提高性能太多。 其实还是很喜欢GO语言,简单,实用,并且适合大规模并发。 围棋学习阈值低于java。 如果担心gc影响实时,也可以申请大量内存做自己的内存管理。也许JavaGC更好,去不够。去并发比较好,Java达到同样效果,回调写死。真的很想知道,只是考...

weixin_36476970的博客 1345

用Python turtle库 绘制皮卡丘

Turtle库是Python语言中一个很流行的绘制图像的函数库,想象一个小乌龟,在一个横轴为x、纵轴为y的坐标系原点,(0,0)位置开始,它根据一组函数指令的控制,在这个平面坐标系中移动,从而在它爬行的路径上绘制了图形。 turtle基础知识参考: https://gitchat.blog.youkuaiyun.com/article/details/90696190 https://blog.csdn.ne...

qq_36295856的博客 2万+

第09章 Go语言并发,Golang并发

并发指在同一时间内可以执行多个任务。并发编程含义比较广泛,包含多线程编程、多进程编程及分布式程序等。本章讲解的并发含义属于多线程编程。 Go 语言通过编译器运行时(runtime),从语言上支持了并发的特性。Go 语言的并发通过goroutine特性完成。goroutine 类似于线程,但是可以根据需要创建多个 goroutine 并发工作。goroutine 是由 Go 语言的运行时调度完成,而线程是由操作系统调度完成。 Go 语言还提供channel在多个 goroutine 间进行通信。gor...

心情第一 1401

准备生日礼物

摘要: 题目要求统计某月份需要准备的员工生日礼物数量。输入包括目标月份、员工姓名列表和对应的生日列表(格式为Year/Month/Day)。需处理重复员工(以最后一次录入为准),统计该月生日的员工人数。示例1中5月有3名员工生日,输出3;示例2中10月有6名,输出6。解题关键在于使用哈希表去重(以员工姓名为键),拆分生日字符串提取月份进行匹配。代码实现(C++/Java/Python)均遵循以下步骤:读取输入、哈希去重、解析月份并统计目标月份人数。时间复杂度为O(n),空间复杂度O(n)。

面试高手的博客 297

Go语言(Golang)高并发处理思路

Go语言作为新兴的语言,最近发展势头很是迅猛,其最大的特点就是原生支持并发。它使用的是“协程(goroutine)模型”,和传统基于 OS 线程和进程实现不同,Go语言的并发是基于用户态的并发,这种并发方式就变得非常轻量,能够轻松运行几万并发逻辑。Go 的并发属于 CSP 并发模型的一种实现,CSP 并发模型的核心概念是:“不要通过共享内存来通信,而应该通 过通信来共享内存”。这在 Go 语言中的实现就是 Goroutine 和 Channel。 1、场景描述 在一些场景下,有大规模请求(十万...

weixin_42117918的博客 1万+

基于FFT+BP神经网络/决策树的轴承故障诊断

基于FFT+BP神经网络/决策树的轴承故障诊断

天天酷科研的博客 131

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Go协程并发之百万级并发「让我们一起Golang」

Go协程并发之百万级并发「让我们一起Golang」 前面我们介绍了关于Golang的协程并发的一些理论知识,接下来我们上代码,通过代码带大家了解一下Go的协程并发,体验Go的百万级并发。 我们先来了解一下进程、线程、协程的区别吧! 进程有自己独立的堆和栈,而线程虽然拥有独立的栈,但是它的堆是共享的。而我们这里要讲的协程和线程是一样的,也是只共享堆,而不共享栈。但是协程不像进程和线程那样由操作系统调度,而是由程序员来调度,这样就可以节省资源,提高性能。 下面来看看主协程和一条协程在并发执行时的表现吧! fun

ReganYue's Blog 1482

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

GoLang之go常用的并发模型

GoLang之go常用的并发模型

weixin_52690231的博客 2083

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

【golang】认识 Go 并发+

总之,Go 使用的是 Goroutines 和 Threads,它们在并发执行函数的组合中都是必不可少的。相比之下,线程开始于一个更大的空间,以及一个称为保护页的内存区域,该区域充当一个线程的内存。它们非常轻量级,不像操作系统线程,而是数百个 Goroutines 可以被多路复用到一个操作系统线程上(Go 有它的运行时调度器) ,只需要最小的上下文切换开销!Scheduler 的工作是将可运行的 goroutine (G)分布在运行在一个或多个处理器(P)上的多个工作 OS 线程(M)上。

qfzhangwei的专栏 623

go java 并发_golang与java并发性能对比测试

测试环境:cpu:2.8 GHz 四核Intel Core i7内存:16 GB 1600 MHz DDR3jdk版本:1.8go版本:1.14测试方法:分别使用golang和java并发执行相同数量的空任务golang使用goroutine实现,代码如下:func main() {count,line := 100*10000,"---------------------------------...

weixin_35657099的博客 1683

【Golang】Go的并发和并行性解释。谁说Go不是并行语言?

偶然发现百度上有很多"师出同门"的"go是并发语言,而不是并行语言"的说法。最终我认为起点大概率是在"Rob Pike"(Go作者之一)于2012年发表的一场演讲,名为"并发不是并行"。之后则被标题党曲解为"go是并发语言,而不是并行语言"。简单说,Rob Pike 用很多"地鼠工人"(gopher)把一个"烧书"任务进行了循序渐进的并发设计,这是一个三只地鼠协同工作的设计,每个地鼠都是一个独立执行的一段程序。

无数_Mirage的博客 708

Go(Golang)并发

超详细的Go的并发使用,易学秒懂!

qq_54129105的博客 848
上一篇: golang基础知识
下一篇: 编程踩坑笔记
code_AC
博客等级 码龄12年 255粉丝 109原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值