美文网首页
Go语言的并发

Go语言的并发

作者: alonwang | 来源:发表于2018-12-03 13:49 被阅读29次

前言

Go是一种静态强类型,``编译型,并发型并且具有垃圾回收的编程语言

以上摘自维基百科Go语言的介绍.
从诞生之初,Go语言就备受瞩目,Google的支持,强大的开发团队,面向现代处理器的编程优化,一切都预示go语言的美好前景.
笔者的主力语言是Java,最近也抽空研究了一下Go语言,查到的资料中描述了很多Go的强大特性,这些特性都很诱人,但是还不足以称为语言的基础,本文将只阐述Go的并发特性.

Go语言的高并发(concurrency)

concurrency(并发) is not parallelism(并行)

Concurrency is about dealing with lots of things at once. Parallelism is about doing lots of things at once.

详见Concurrency is not parallelism

Go的并发基础: goroutine

A goroutine is a lightweight thread managed by the Go runtime.

goroutine是由Go runtime管理的比轻量级线程(LWP)更轻量的线程(姑且这么叫吧),它的开销很小,可以轻易的同时启动成千上万个goroutine,设想一下 Java中开启10个线程的消耗在Go语言中可以用来开启100甚至1000个goroutine,显然Go语言的运行效率会更高,要明白goroutine到底是什么,让我们先从线程开始讲起

从线程开始

线程的基础概念

线程分为三类kernel threads, user threads, and fibers

kernel threads 内核线程

kernel thread是由操作系统内核支持的线程,也是基本意义上的线程,kernel thread切换由内核完成.一般程序不会直接使用kernel thread,而是使用kernel thread的一种高级接口-轻量级进程(Light Weight Process)一个LWP对应于一个kernel thread.

user threads 用户线程

user thread指不需要内核支持而在用户程序中实现的线程,它不依赖于内核,用户自己实现user thread的创建,同步,调度,管理等功能.这里一个LWP对应多个user thread,简单点说 一个进程拥有多个LWP,一个LWP又拥有多个user thread.,这里的用户一般指的是编程语言

fiber 混合

两者的混合,折中方案,不多说

它们的优缺点都是什么

对于kernel thread和user thread,站在编程语言的角度来看,都有什么优缺点

kernel thread

kernel thread的优点:

  1. kernel thread由内核管理,使用kernel thread时调用LWP的函数即可,对于编程语言来说实现简单
  2. 对于多核处理器,内核可以将线程调度到其他核心上运行,可以充分利用多核的优势

kernel thread的缺点:

  1. kernel thread的管理需要系统调用,而系统调用需要在用户态和内核态切换,代价很高
  2. 由于LWP和kernel thread是1:1的,每个LWP都要消耗一部分内核资源,这也限制了kernel thread的数量
user thread

user thread的优点:

  1. user thread的切换由编程语言控制,不涉及内核,也就很少需要内核态和用户态的切换,效率高
  2. 一个LWP对应多个user thread,因此user thread的数量要大大超过LWP.意味着更高的并发

user thread的缺点:

  1. 需要自己实现user thread的管理,很困难
  2. user thread是由用户管理的,而内核只能控制到LWP,那么在多核处理器下,user thread只能在某个核心上的某个线程上跑,无法充分利用多核优势
  3. 如果某个user thread由于某些原因被阻塞,那么这个LWP上的所有user thread都被阻塞了

综上所述,kernel thread由内核控制,使用简单但是效率不够高.user thread由用户(编程语言)实现,效率很高,但是实现起来比较复杂.
在讲Go语言使用了哪种线程模式之前,先来看下Java

Java为什么从user thread转为kernel thread?

JDK1.2时使用的还是user thread,Java的开发团队称之为Green Thread,为什么后面切换到了kernel thread呢?
查阅资料后在这里找到了原因,sco的说明
大致有一下两点原因

  1. Java开发团队在实现Green Threads时,为了达到非阻塞IO,对系统调用做了封装,但是某些JNI调用会打破这个封装,导致一些很严重的问题
  2. Green Threads无法充分利用多核优势,原因同user thread的缺点2

还有以下说明

here is a significant processing overhead for the JVM to keep track of thread states and swap between them, so green thread mode has been deprecated and removed from more recent Java implementations

总体来看是Java开发团队由于时代背景,user thread的实现有缺陷,因此才切换到kernel thread的线程模式

Go使用了哪个线程模型

Go使用了user thread的线程模型,在Go中称之为goroutine,这是Go称为并发型语言的基础.
Go语言中有逻辑处理器(Logic Processor)的概念,,通过它完成user thread的调度.

下面看下goroutine如何解决user thread的缺陷

如何处理阻塞的user thread

下图截取自 <Go In Action>,可以看到当goroutine执行了阻塞的系统调用后,调度器将这个LWP与LP分离,并创建一个新的LWP为这个LP提供服务

img_20181202_131243.010.png
如何充分利用多核

参见Fork/Join中的工作窃取算法,TODO

再谈内存模型

关于内存模型,参见共享内存和消息传递,总结一下

共享内存的通信是隐式的,线程之间通过写-读内存中的公共状态来隐式通信,而线程之间的同步是显式的,必须在代码中写好同步逻辑.
消息传递的通信是显式的,线程之间通过明确的发送消息来通信,由于收消息肯定在发消息之后,因此线程之间的同步是隐式的

目前的语言大都共享内存,为什么不用消息传递?以前的编程语言大都使用了kernel thread模式,而在kernel thread之间传递消息消耗太大,因此只能选择代码编写更麻烦的共享内存模型

Go使用了哪种内存模型

消息传递!,Go使用了user thread的线程模式.消息传递的消耗不再成为问题,自然要选择更有利于并发的消息传递模型,在Go中,消息传递主要通过chan这个结构完成chan即通道.类似于Java nio中通道的概念.goroutine通过在chan中发送/读取消息实现同步.

结语

本文简要说明了Go语言高并发的实现基础,可以看到Go的高并发是语言设计时天生的优势.


相关文章

  • Go语言并发

    Go语言并发 Go语言级别支持协程,叫做goroutine Go 语言从语言层面支持并发和并行的开发操作 Go并发...

  • Go基础语法(九)

    Go语言并发 Go 是并发式语言,而不是并行式语言。 并发是指立即处理多个任务的能力。 Go 编程语言原生支持并发...

  • Go 并发原理

    Go语言是为并发而生的语言,Go语言是为数不多的在语言层面实现并发的语言;也正是Go语言的并发特性,吸引了全球无数...

  • GO语言初级学习之代码案例13 (QQ群聊)

    @(go语言 黑马)[GO语言] 并发聊天室 题目:利用Go语言高并发的特性,编写一个类似QQ群聊功能的并发聊天服...

  • Go并发

    并发和并行 Go是并发语言,而不是并行语言。(Go is a concurrent language and no...

  • Go并发

    Go语言中的并发编程 并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发,这也是Go语言流行的一个很...

  • 第14章-并发性Concurrency

    并发性Concurrency 1.1 什么是并发 Go是并发语言,而不是并行语言。在讨论如何在Go中进行并发处理之...

  • Golang(十四) 并发性Concurrency

    并发性Concurrency 1.1 什么是并发 Go是并发语言,而不是并行语言。在讨论如何在Go中进行并发处理之...

  • Go语言的并发,你做对了吗?

    ​ Go语言的并发,你做对了吗? 并发性是go语言一个非常核心的卖点。这一期我们就来看一下,Go语言的并发性。 [...

  • 跟我一起学习GO语言008

    本节我们来看GO语言中的并发。 我们看并发,就不得不学习goroutine,goroutine是Go语言...

网友评论

      本文标题:Go语言的并发

      本文链接:https://www.haomeiwen.com/subject/aydycqtx.html