前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go编程基础-基础篇 19

Go编程基础-基础篇 19

原创
作者头像
未来最可爱的人
修改2021-04-01 17:56:53
2730
修改2021-04-01 17:56:53
举报
文章被收录于专栏:编程基础编程基础

goroutine

可以近乎无限开启的线程。在 Go 语言中被称之为 goroutine ,它是线程的轻量级实现。

在 Go 语言中使用 go 关键字来创建 goroutine ,形如go 函数名()的形式去创建。每一个 goroutine 必须是一个函数,这个函数也可以是匿名函数。

代码语言:txt
复制
package main

import (

"fmt"

"time"

)

func print0to10() {

for i := 0; i <= 10; i++ {

fmt.Println("print0to10:", i)

time.Sleep(time.Microsecond)

}

}

func main() {

go print0to10()

go func() {

for i := 'A'; i <= 'K'; i++ {

fmt.Println("printAtoK:", string(i))

time.Sleep(time.Microsecond)

}

}()

time.Sleep(time.Second)

}
代码语言:txt
复制
print0to10: 0

print0to10: 1

printAtoK: A

print0to10: 2

printAtoK: B

printAtoK: C

printAtoK: D

print0to10: 3

print0to10: 4

printAtoK: E

print0to10: 5

printAtoK: F

printAtoK: G

printAtoK: H

print0to10: 6

printAtoK: I

print0to10: 7

printAtoK: J

print0to10: 8

printAtoK: K

print0to10: 9

print0to10: 10

并发通讯

其它语言并发时进程中的通讯一般都是通过共享内存(全局变量)的方式来实现的,这样一来各个模块之间的耦合会变得非常紧密。所以后来提出了使用通讯来共享内存这一概念,来解耦合。在 Go 语言中就是使用 channel 的方式来达到这一目的的。

代码语言:txt
复制
package main

import (

"fmt"

"time"

)

var c1 chan rune = make(chan rune, 0)

var c2 chan int = make(chan int, 0)

func print0to10() {

for i := 'A'; i <= 'K'; i++ {

num := <-c2

fmt.Println("print0to10:", num)

c1 <- i

}

}

func main() {

go print0to10()

go func() {

c2 <- 0

for i := 1; i <= 11; i++ {

char := <-c1

fmt.Println("printAtoK:", string(char))

c2 <- i

}

}()

time.Sleep(time.Second)

}
代码语言:txt
复制
print0to10: 0

printAtoK: A

print0to10: 1

printAtoK: B

print0to10: 2

printAtoK: C

print0to10: 3

printAtoK: D

print0to10: 4

printAtoK: E

print0to10: 5

printAtoK: F

print0to10: 6

printAtoK: G

print0to10: 7

printAtoK: H

print0to10: 8

printAtoK: I

print0to10: 9

printAtoK: J

print0to10: 10

printAtoK: K

语言进程锁

线程不安全的 map 。之所以线程不安全是因为其内部实现机制中无法同时读写,若有两个 goroutine 一个在读取 map 中的值,而另一个在更新 map 中的值,就会导致程序崩溃。

代码语言:txt
复制
package main

import (

"fmt"

"time"

)

func main() {

m := map[string]int{"A": 1, "B": 2, "C": 3, "D": 1, "E": 2, "F": 3}

for i := 0; i < 100; i++ {

go func() {

for v := range m {

m[v] = 100

}

}()

}

time.Sleep(time.Second)

fmt.Println(m)

}
代码语言:txt
复制
fatal error: concurrent map writes

这个就是线程不安全的 map 不建议使用的原因,除了直接使用线程安全的 map 之外,还可以为这些 goruntine 加上锁,使其无法同时对 map 进行读写操作,这样也可以保障各线程的安全。

代码语言:txt
复制
package main

import (

"fmt"

"sync"

"time"

)

func main() {

var lock sync.Mutex

m := map[string]int{"A": 1, "B": 2, "C": 3, "D": 1, "E": 2, "F": 3}

for i := 0; i < 100; i++ {

go func() {

lock.Lock()

for v := range m {

m[v] = 100

}

lock.Unlock()

}()

}

time.Sleep(time.Second)

fmt.Println(m)

}
代码语言:txt
复制
map[A:100 B:100 C:100 D:100 E:100 F:100]

goroutine 执行无先后顺序,由 cpu 统一调度。

goroutine 之间内存的共享通过使用 channel 来通讯实现。

goroutine 使用线程不安全的变量类型时可以用锁将其锁定。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • goroutine
  • 并发通讯
  • 语言进程锁
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档