美文网首页
并发编程

并发编程

作者: 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