美文网首页
并发编程

并发编程

作者: isuntong | 来源:发表于2020-03-24 17:47 被阅读0次

介绍

线程:轻量级进程
携程:轻量级线程

并发

协程

mac活动监视器=任务管理器

线程:进程中的执行路径

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)
    }
}

主goroutine结束,程序就结束了,不管子goroutine,可以用管道通信

与函数不同,所以写了返回值也没有用

启动多个goroutine

并发模型

runtime包

类似与虚拟机,管理内存

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函数")
}

临界资源的安全问题

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)

}
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
        }
    }
}

不鼓励通过共享内存通信,鼓励通过通信来共享内存

channel

sync包下的WaitGroup同步等待组

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)
    }
}

如果没有wg.Done()

如果是1,随便抓一个

互斥锁

互斥锁、读写锁

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()
    }
}

建议使用defer语句解锁

读写锁

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://www.haomeiwen.com/subject/zevtyhtx.html