介绍
线程:轻量级进程
携程:轻量级线程
并发
![](https://img.haomeiwen.com/i17476301/1c5ac24046f73097.png)
![](https://img.haomeiwen.com/i17476301/8dde32a933df8edd.png)
![](https://img.haomeiwen.com/i17476301/fef1a6e6c819fe7e.png)
![](https://img.haomeiwen.com/i17476301/b9c910d2207e192b.png)
![](https://img.haomeiwen.com/i17476301/b5cbec3863bb1bd7.png)
![](https://img.haomeiwen.com/i17476301/f3d412e9ccf6c761.png)
![](https://img.haomeiwen.com/i17476301/c5f44dbed0dec470.png)
![](https://img.haomeiwen.com/i17476301/a55422beb71abcb0.png)
协程
![](https://img.haomeiwen.com/i17476301/08e4e279dcf17bcd.png)
mac活动监视器=任务管理器
线程:进程中的执行路径
![](https://img.haomeiwen.com/i17476301/9f555ca1ab8628ba.png)
![](https://img.haomeiwen.com/i17476301/e56b89162d2d6191.png)
![](https://img.haomeiwen.com/i17476301/82a2f5d985e63735.png)
![](https://img.haomeiwen.com/i17476301/2ada76fc250869a4.png)
package main
import "fmt"
//9
func main() {
/*
一个goroutine打印数字,另外一个goroutine打印字母,观察运行结果
*/
//1. 先创建并启动子goroutine,执行printNum()
go printNum()
//2. main打印字母
for i:=1;i<=100;i++ {
fmt.Printf("\t主goroutine打印字母:A %d\n",i)
}
fmt.Println("main over...")
}
func printNum(){
for i:=1;i<=100;i++ {
fmt.Printf("子goroutine打印数字:%d\n",i)
}
}
![](https://img.haomeiwen.com/i17476301/c8d994aca15eb13b.png)
主goroutine结束,程序就结束了,不管子goroutine,可以用管道通信
与函数不同,所以写了返回值也没有用
启动多个goroutine
![](https://img.haomeiwen.com/i17476301/74a1e710ffce647b.png)
![](https://img.haomeiwen.com/i17476301/cf8c988768bc2d3e.png)
并发模型
![](https://img.haomeiwen.com/i17476301/cf2f5b3368f741bb.png)
![](https://img.haomeiwen.com/i17476301/9a60c3d1576f8a5d.png)
![](https://img.haomeiwen.com/i17476301/0b392695fb6f37c1.png)
![](https://img.haomeiwen.com/i17476301/bd897f0404551db9.png)
![](https://img.haomeiwen.com/i17476301/a9af211d75cd7b4e.png)
![](https://img.haomeiwen.com/i17476301/36a0d413433ade98.png)
![](https://img.haomeiwen.com/i17476301/69575fdbc81517d2.png)
![](https://img.haomeiwen.com/i17476301/b2ab62ad56ac1c31.png)
![](https://img.haomeiwen.com/i17476301/b50a38da76ae86e7.png)
![](https://img.haomeiwen.com/i17476301/ab9dfaeca2bdcdee.png)
![](https://img.haomeiwen.com/i17476301/486bccaf7e035d77.png)
![](https://img.haomeiwen.com/i17476301/ac014374bf5ea2a5.png)
![](https://img.haomeiwen.com/i17476301/fd2a9d38148be33e.png)
![](https://img.haomeiwen.com/i17476301/6327e0ad575a59f7.png)
![](https://img.haomeiwen.com/i17476301/17ec168fd233b7a8.png)
runtime包
![](https://img.haomeiwen.com/i17476301/a985110525e488fc.png)
类似与虚拟机,管理内存
![](https://img.haomeiwen.com/i17476301/0032e23258a43258.png)
package main
import (
"fmt"
"runtime"
"time"
)
//10
func main() {
//获取goroot目录
fmt.Println("GOROOT---->",runtime.GOROOT()) //GOROOT----> /usr/local/go
//获取操作系统
fmt.Println("os/platform---->",runtime.GOOS) //os/platform----> darwin,mac系统
//获取逻辑cpu的数量
fmt.Println("逻辑CPU的数量---->",runtime.NumCPU()) //逻辑CPU的数量----> 8
//设置cpu数量,不要乱写,写当前逻辑cpu数量就行,最好写在init函数
//n := runtime.GOMAXPROCS(16)
//fmt.Println(n)
//gosched让出当前时间片,让别的goroutine先执行
go func(){
for i := 0; i < 5; i++ {
fmt.Println("goroutine...")
}
}()
for i := 0; i < 5; i++ {
//让出时间片,先让别的goroutine执行
runtime.Gosched()
fmt.Println("main...")
}
//创建goroutine
go func() {
fmt.Println("goroutine开始")
//调用fun
fun()
fmt.Println("goroutine结束")
}()
//睡一会
time.Sleep(3 * time.Second)
}
func fun(){
defer fmt.Println("defer...")
// return //终止函数
runtime.Goexit() //终止当前的goroutine
fmt.Println("fun函数")
}
![](https://img.haomeiwen.com/i17476301/43b6a27e015fdc3b.png)
临界资源的安全问题
![](https://img.haomeiwen.com/i17476301/3ff88b9f2c5c7de5.png)
package main
import (
"fmt"
"time"
)
//11
func main() {
/*
临界资源
*/
a := 1
go func() {
a = 2
fmt.Println("goroutine中a:",a)
}()
a = 3
time.Sleep(1)
fmt.Println("main goroutine...",a)
}
![](https://img.haomeiwen.com/i17476301/a60ba2722adcd543.png)
![](https://img.haomeiwen.com/i17476301/885a954e0f0f20f2.png)
package main
import (
"fmt"
"math/rand"
"time"
)
//11
func main() {
/*
临界资源
*/
a := 1
go func() {
a = 2
fmt.Println("goroutine中a:",a)
}()
a = 3
time.Sleep(1)
fmt.Println("main goroutine...",a)
/*
4个goroutine,模拟4个售票口
*/
go saleTickets("售票口1")
go saleTickets("售票口2")
go saleTickets("售票口3")
go saleTickets("售票口4")
time.Sleep(5 * time.Second)
}
//全局变量
var ticket = 10
func saleTickets(name string) {
for{
if ticket > 0 {
rand.Seed(time.Now().UnixNano())
time.Sleep(time.Duration(rand.Intn(1000))*time.Millisecond)
fmt.Println(name,"售出",ticket)
ticket--
}else {
fmt.Println(name,"售罄,没有票了。。")
break
}
}
}
![](https://img.haomeiwen.com/i17476301/3a308d42460c45d9.png)
![](https://img.haomeiwen.com/i17476301/82a02fa90e7650d5.png)
![](https://img.haomeiwen.com/i17476301/53cd05a174b00d4b.png)
不鼓励通过共享内存通信,鼓励通过通信来共享内存
channel
sync包下的WaitGroup同步等待组
![](https://img.haomeiwen.com/i17476301/565b194a1d58236c.png)
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup //创建同步等待组的对象
//11
func main() {
/*
waitgroup:同步等待组
Add(),设置等待组中要执行的子 goroutine 的数量
Wait(),让主goroutine等待
*/
wg.Add(2)
go fun1()
go fun2()
//无输出
fmt.Println("main进入阻塞,等待wg的子groutine结束")
wg.Wait()
fmt.Println("main阻塞解除")
}
func fun1(){
for i := 1; i < 10; i++ {
fmt.Println("fun1打印 a", i)
}
wg.Done() //给wg等待组count数值减1 == add(-1)
}
func fun2(){
defer wg.Done()
for i := 1; i < 10; i++ {
fmt.Println("\tfun2打印 b", i)
}
}
![](https://img.haomeiwen.com/i17476301/22cd185316c5a467.png)
如果没有wg.Done()
![](https://img.haomeiwen.com/i17476301/0fb6eb05b554e987.png)
如果是1,随便抓一个
![](https://img.haomeiwen.com/i17476301/43342862ec1e5642.png)
![](https://img.haomeiwen.com/i17476301/d0ced35806812a93.png)
互斥锁
![](https://img.haomeiwen.com/i17476301/277d72cbf0af791c.png)
互斥锁、读写锁
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
var wg sync.WaitGroup
//13
func main() {
/*
4个goroutine,模拟4个售票口
*/
wg.Add(4)
go saleTickets2("售票口1")
go saleTickets2("售票口2")
go saleTickets2("售票口3")
go saleTickets2("售票口4")
wg.Wait()
fmt.Println("main over")
}
//全局变量
var ticket = 10
var mutex sync.Mutex //创建锁
func saleTickets2(name string) {
rand.Seed(time.Now().UnixNano())
defer wg.Done()
for{
//上锁
mutex.Lock()
if ticket > 0 {
time.Sleep(time.Duration(rand.Intn(1000))*time.Millisecond)
fmt.Println(name,"售出",ticket)
ticket--
}else {
mutex.Unlock() //条件不满足也要解锁
fmt.Println(name,"售罄,没有票了。。")
break
}
//解锁
mutex.Unlock()
}
}
![](https://img.haomeiwen.com/i17476301/76acec21bd502890.png)
建议使用defer语句解锁
读写锁
![](https://img.haomeiwen.com/i17476301/88b001479ebd4ee6.png)
![](https://img.haomeiwen.com/i17476301/385c7d88a4b2d927.png)
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
var rwMutex *sync.RWMutex
//14
func main() {
/*
读写锁
*/
rwMutex = new(sync.RWMutex)
//wg.Add(2)
//
////读操作可以同时进行
//go readData(1)
//go readData(2)
wg.Add(3)
go writeData(1)
go readData(2)
go writeData(3)
wg.Wait()
fmt.Println("main over")
}
func writeData(i int){
defer wg.Done()
fmt.Println(i,"开始写:write start。。")
rwMutex.Lock() //读操作上锁
fmt.Println(i,"正在写")
time.Sleep(1 * time.Second)
rwMutex.Unlock() //读操作解锁
fmt.Println(i,"写结束:write over")
}
func readData(i int){
defer wg.Done()
fmt.Println(i,"开始读:read start。。")
rwMutex.RLock() //读操作上锁
fmt.Println(i,"正在读取")
time.Sleep(1 * time.Second)
rwMutex.RUnlock() //读操作解锁
fmt.Println(i,"读结束:read over")
}
![](https://img.haomeiwen.com/i17476301/ed5a7ddef7551d23.png)
![](https://img.haomeiwen.com/i17476301/68a1c79d605a5d7b.png)
网友评论