• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Golang进阶

武飞扬头像
RNGWGzZs
帮助1

学新通

"白昼会边长,照亮心脏,让万物生长。"

一、Golang进阶

我们对golang的语法进行了一定的了解后,也算是入门了。本节的进阶篇围绕三个方向展开,Goroutine 、 Channel 、Sync。

如何理解并行与并发?

并行是指“并排行走”或“同时实行或实施”。
在操作系统中是指,一组程序按独立异步的速度执行,无论从微观还是宏观,程序都是一起执行的。对比地,并发是指:在同一个时间段内,两个或多个程序执行,有时间上的重叠(宏观上是同时,微观上仍是顺序执行)

并发,在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行,但任一个时刻点上只有一个程序在处理机上运行。

下面两张图就可以区别并发与并行;

并发:

学新通

并行:

学新通

同样,随着技术的迭代升级也有了并行 并发:

学新通
看完上面的图解。
并发的实质是针对单核CPU,它的交替调度不同任务的能力
并行的是追是针对多核CPU,它指的是多个核心同时执行多个任务的能力。
由此,单核 CPU 只能并发,无法并行。并行,只存在于多核CPU的硬件条件下。
而在多核CPU中,并发并行都会同时存在,这是提高CPU处理任务能力的重要手段

(1)Goroutine

协程,又叫做轻量级线程。这在Golang这样的编程语言中特别流行。

Go协程的特点:
1.独立的栈空间
2.共享堆空间
3. 协程调度由用户控制(进程的控制是有操作系统控制,程序员不能控制)

不管是父进程创建的子进程,还是在linuxPOSIX提供的线程库。其中的管理都是交由操作系统。因此,在程序执行的过程中,总会存在执行状态的切换(用户到内核,内核到用户)。但是,golang中的协程完完全全解决了这个问题。

协程:用户态,轻量级线程。
线程:内核态,线程可以跑多个协程。
创建一个线程栈大概需要 1MB 左右,而协程栈大概只需要几 KB或者几十KB。
  1.  
    package main
  2.  
     
  3.  
    import (
  4.  
    "fmt"
  5.  
    "time"
  6.  
    )
  7.  
     
  8.  
    func hello(i int) {
  9.  
    fmt.Println("go() to hello", i)
  10.  
    }
  11.  
     
  12.  
    func HelloRotinue() {
  13.  
    for i := 0; i < 5; i {
  14.  
    go hello(i)
  15.  
    }
  16.  
    time.Sleep(time.Second)
  17.  
    }
  18.  
     
  19.  
    func main() {
  20.  
    HelloRotinue()
  21.  
    for i := 0; i < 5; i {
  22.  
    fmt.Println("main() to hello", i)
  23.  
    time.Sleep(time.Second)
  24.  
    }
  25.  
    }
学新通

我们在调用打印hello的函数前面加上关键字"go"。表面,我们起一个协程来调用这个函数。

学新通

但我们此时没有设置HelloRotinue为线程,因此是等待该函数调用完时,才开始进行主线程main。

学新通

此时,只需要在该函数前加上go,这两个执行流就不会处在所谓的"阻塞"状态,而是各管各的。

什么是CSP?

CSP理念: 以通信的方式来共享内存。Go 的并发哲学,依赖于 CSP 模型。

大多数编程语言,在如何实现并发的问题上,采用的都是基于线程和内存同步访问控制。而Go 的并发编程的模型则用 goroutine 和 channel 来替代。

Goroutine 和线程类似,channel 和 mutex (用于内存同步访问控制的互斥锁)类似。

我们在linux处着重讲了,实现进程间的本质,就是让每个进程(线程)可看到同一份公共资源。而这个而资源,也叫做临界区。

通过共享内存实现通信;

学新通

通过通信共享内存;

学新通

(2)Channel

make(chan 元素类型,[缓冲大小])
例如:
无缓冲通道 make(chan int)
有缓冲通道 make(chan int,2)

比如,现在我们要执行完成一个任务。协程1发送0~9数字,协程2拿到数字后计算它们的平方,并发送给主线程,并在主线程处打印。

学新通

最后我们也可以得到结果。

学新通

(3)Sync

sync(意指Synchronize,即“同步”)为UNIX操作系统的标准系统调用,功能为将内核文件系统缓冲区的所有数据。

sync:
Package sync provides basic synchronization primitives such as mutual exclusion locks. Other than the Once and WaitGroup types, most are intended for use by low-level library routines. Higher-level synchronization is better done via channels and communication.

包同步提供了基本的同步原语,如互斥锁。除了Once和WaitGroup类型之外,大多数类型都是供低级库例程使用的。更高级别的同步最好通过信道和通信来完成。

并发安全 Lock

我们期待五个协程对x进行2000循环地自增加1

  1.  
    package main
  2.  
     
  3.  
    import (
  4.  
    "fmt"
  5.  
    "sync"
  6.  
    "time"
  7.  
    )
  8.  
     
  9.  
    var (
  10.  
    x int64
  11.  
    lock sync.Mutex
  12.  
    )
  13.  
     
  14.  
    func addWithLock() {
  15.  
    for i := 0; i < 2000; i {
  16.  
    lock.Lock()
  17.  
    x = 1
  18.  
    lock.Unlock()
  19.  
    }
  20.  
    }
  21.  
     
  22.  
    func addWithOutLock() {
  23.  
    for i := 0; i < 2000; i {
  24.  
    x = 1
  25.  
    }
  26.  
    }
  27.  
     
  28.  
    func main() {
  29.  
    x = 0
  30.  
    for i := 0; i < 5; i {
  31.  
    go addWithOutLock()
  32.  
    }
  33.  
    fmt.Println("WithOutLock: ", x)
  34.  
    time.Sleep(time.Second)
  35.  
     
  36.  
    x = 0
  37.  
    for i := 0; i < 5; i {
  38.  
    go addWithLock()
  39.  
    }
  40.  
    time.Sleep(time.Second)
  41.  
    fmt.Println("WithLock: ", x)
  42.  
    }
学新通
学新通

WaitGroup

学新通

这个类里有三个比较重要的函数;

学新通

我们简简单单地用五个协程分别打印。

学新通

我们对代码进行一定的改进。让打印后的结果进行阻塞。

学新通
学新通

总结:

本篇也就到此结束了~感谢你的阅读

祝你好运,向阳而生

学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfbcfc
系列文章
更多 icon
同类精品
更多 icon
继续加载