Go:并发与多线程

1. 概念

            A. 并发:同一时间段内执行多个操作。

            B. 并行:同一时刻执行多个操作。

2. 多线程 Goroutine初探

            A. 线程是由操作系统进行管理,也就是处于内核态。

            B. 线程之间进行切换,需要发生用户态到内核态的切换。

            C. 当系统中运行大量线程,系统会变的非常慢。

            D. 用户态的线程,支持大量线程创建。也叫协程或goroutine。

3. 创建goroutine

package main
import (
    "fmt"
)

func hello() {
    fmt.Println("Hello world goroutine")
}

func main() {
    go hello()
    fmt.Println("main function")
}

4. 修改代码

package main
import (
    "fmt“
    “time”
)

func hello() {
    fmt.Println("Hello world goroutine")
}

func main() {
    go hello()
    time.Sleep(1*time.Second)
    fmt.Println("main function")
}

5. 启动多个goroutine

package main
import (
    "fmt"
    "time"
)

func numbers() {
    for i := 1; i <= 5; i++ {
        time.Sleep(250 * time.Millisecond)
        fmt.Printf("%d ", i)
    }
}

func alphabets() {
    for i := 'a'; i <= 'e'; i++ {
        time.Sleep(400 * time.Millisecond)
        fmt.Printf("%c ", i)
    }
}

func main() {
    go numbers()
    go alphabets()
    time.Sleep(3000 * time.Millisecond)
    fmt.Println("main terminated")
}

8. 多核控制

            A. 通过runtime包进行多核设置

            B. GOMAXPROCS设置当前程序运行时占用的cpu核数

            C. NumCPU获取当前系统的cpu核数

9. Goroutine原理浅析

            A. 一个操作系统线程对应用户态多个goroutine

            B. 同时使用多个操作系统线程

            C. 操作系统线程对goroutine是多对多关系,即M:N

10. 模型抽象

            A. 操作系统线程: M

            B. 用户态线程(goroutine): G

            C. 上下文对象:P

11. goroutine调度

12. 系统调用怎么处理

channel介绍

13. channel介绍

            A. 本质上就是一个队列,是一个容器

            B. 因此定义的时候,需要只定容器中元素的类型

            C. var 变量名 chan 数据类型

package main
import "fmt"

func main() {
    var a chan int
    if a == nil {
        fmt.Println("channel a is nil, going to define it")
        a = make(chan int)
        fmt.Printf("Type of a is %T", a)
    }
}

14. 元素入队和出队 

            A. 入队操作,a <- 100

            B. 出队操作:data := <- a

15. 阻塞chan

package main

import "fmt"

func main() {
    var a chan int
    if a == nil {
        fmt.Println("channel a is nil, going to define it")
        a = make(chan int)
        a <- 10
        fmt.Printf("Type of a is %T", a)
    }
}

16. 使用chan来进行goroutine同步

package main
import (
"fmt"
)

func hello(done chan bool) {
    fmt.Println("Hello world goroutine")
    done <- true
}

func main() {
    done := make(chan bool)
    go hello(done)
    <-done
    fmt.Println("main function")
}

17. 使用chan来进行goroutine同步

package main
import (
    "fmt"
    "time"
)

func hello(done chan bool) {
    fmt.Println("hello go routine is going to sleep")
    time.Sleep(4 * time.Second)
    fmt.Println("hello go routine awake and going to write to done")
    done <- true
}

func main() {
    done := make(chan bool)
    fmt.Println("Main going to call hello go goroutine")
    go hello(done)
    <-done
    fmt.Println("Main received data")
}

18. 单向chan

package main

import "fmt"

func sendData(sendch chan<- int) {
    sendch <- 10
}

func readData(sendch <-chan int) {
    sendch <- 10
}

func main() {
    chnl := make(chan int)
    go sendData(chnl)
    readData(chn1)
}

19. chan关闭

package main
import (
    "fmt"
)

func producer(chnl chan int) {
    for i := 0; i < 10; i++ {
        chnl <- i
    }
    close(chnl)
}

func main() {
    ch := make(chan int)
    go producer(ch)
    for {
        v, ok := <-ch
        if ok == false {
        break
        }
        fmt.Println("Received ", v, ok)
    }
}

20. for range操作

package main

import (
    "fmt"
)

func producer(chnl chan int) {
    for i := 0; i < 10; i++ {
        chnl <- i
    }
    close(chnl)
}

func main() {
    ch := make(chan int)
    go producer(ch)
    for v := range ch {
        fmt.Println("Received ",v)
    }
}

21. 带缓冲区的chanel

            A. Ch := make(chan type, capacity)

 

package main

import (
    "fmt"
)

func main() {
    ch := make(chan string, 2)
    ch <- “hello"
    ch <- “world"
    fmt.Println(<- ch)
    fmt.Println(<- ch)
}

 

package main

import (
    "fmt"
    "time"
)

func write(ch chan int) {
    for i := 0; i < 5; i++ {
        ch <- i
        fmt.Println("successfully wrote", i, "to ch")
    }
    close(ch)
}

func main() {
    ch := make(chan int, 2)
    go write(ch)
    time.Sleep(2 * time.Second)
    for v := range ch {
        fmt.Println("read value", v,"from ch")
        time.Sleep(2 * time.Second)
    }
}

22. channel的长度和容量

            A. Ch := make(chan type, capacity)

package main
import (
    "fmt"
)
func main() {
    ch := make(chan string, 3)
    ch <- "naveen"
    ch <- "paul"
    fmt.Println("capacity is", cap(ch))
    fmt.Println("length is", len(ch))
    fmt.Println("read value", <-ch)
    fmt.Println("new length is", len(ch))
}

23. 如何等待一组goroutine结束?

            A. 方法一,使用不带缓冲区的channel实现

package main
import (
    "fmt"
    "time"
)

func process(i int, ch chan bool) {
    fmt.Println("started Goroutine ", i)
    time.Sleep(2 * time.Second)
    fmt.Printf("Goroutine %d ended\n", i)
    ch <- true
}

func main() {
    no := 3
    exitChan := make(chan bool, no)
    for i := 0; i < no; i++ {
        go process(i, exitChan)
    }
    for i := 0; I < no;i++{
        <-exitChan
    }
    fmt.Println("All go routines finished executing")
}

            B. 方法二,使用sync.WaitGroup实现

package main

import (
    "fmt"
    "sync"
    "time"
)

func process(i int, wg *sync.WaitGroup) {
    fmt.Println("started Goroutine ", i)
    time.Sleep(2 * time.Second)
    fmt.Printf("Goroutine %d ended\n", i)
    wg.Done()
}

func main() {
    no := 3
    var wg sync.WaitGroup
    for i := 0; i < no; i++ {
        wg.Add(1)
        go process(i, &wg)
    }
    wg.Wait()
    fmt.Println("All go routines finished executing")
}

25. worker池的实现

            A. 生产者、消费者模型,简单有效

            B. 控制goroutine的数量,防止goroutine泄露和暴涨

            C. 基于goroutine和chan,构建workerpool非常简单

26. 项目需求分析

            A. 计算一个数字的各个位数之和,比如123,和等于1+2+3=6

            B. 需要计算的数字使用随机算法生成

27. 方案介绍

            A. 任务抽象成一个个job

            B. 使用job队列和result队列

            C. 开一组goroutine进行实际任务计算,并把结果放回result队列

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值