zoukankan      html  css  js  c++  java
  • 8.2 Go 锁

    8.2 Go 锁

    案例(坑):多个goroutine操作同一个map。

    go提供了一种叫map的数据结构,可以翻译成映射,对应于其他语言的字典、哈希表。借助map,可以定义一个键和值,然后可以从map中获取、设置和删除这个值,尤其适合数据查找的场景。

    但是map的使用有一定的限制,如果是在单个协程中读写map,那么不会存在什么问题,如果是多个协程并发访问一个map,有可能会导致程序退出,并打印下面错误信息。

    fatal error: concurrent map writes
    

    错误案例代码

    package main
    
    var myMap = make(map[int]int, 10)
    
    //要求计算50的阶乘结果
    //阶乘就是1*2*3*4...50 =?
    
    func test(n int) {
        //定义初始值1
        res := 1
        //每次循环进行阶乘
        for i := 0; i <= n; i++ {
            res *= i
        }
        //最终计算结果,写入map
        //由于多个协程同时操作map,引发资源竞争报错
        myMap[n] = res
    
    }
    func main() {
        //开启50个协程
        for i := 0; i < 10; i++ {
            go test(10)
        }
    }
    

    并发访问map是不安全的操作,在协程中访问map,必须提供某种同步资源机制,使用sync.Mutex互斥锁同步解决协程的竞争问题。

    package main
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    var lock sync.Mutex
    
    func Printer(str string) {
        //我现在开始使用打印机了,其他人都等我完事了再来
        lock.Lock()
        for _, data := range str {
            fmt.Printf("%c", data)
            time.Sleep(time.Second)
        }
        //我完事了,你们上吧
        lock.Unlock()
        fmt.Printf("
    ")
    }
    
    func Alex() {
        Printer("hello")
    }
    func Wupeiqi() {
        Printer("oldboy")
    }
    
    func main() {
        //coffe(10)//单线程执行函数
        go Alex()
        go Wupeiqi()
        //主线程等待协程结束后 再退出
        time.Sleep(time.Second * 10)
    }
    

    结论:

    1.可以使用加锁的方式解决goroutine的通讯。
    2.主线程等待所有goroutine的时间难以确定,设置固定的等待时间肯定不合理。
    3.对全局变量加锁同步来通讯,也不利于多个协程对变量的读写。
    4.要让主线程等待所有goroutine退出后在退出,如何知道所有goroutine都退出了呢?
    5.因此,channel应运而生!!
  • 相关阅读:
    构造方法
    封装 private
    局部变量和成员变量区别
    IOC
    Linux端口占用查询命令
    Nginx小白入门实战
    SQL left join right join inner join之间的区别
    IDEA导入maven工程时,不会自动识别怎么办
    Spring中Controller层中的method显示为灰色并且提示method is never used的原因
    查看服务器公网IP
  • 原文地址:https://www.cnblogs.com/open-yang/p/11256901.html
Copyright © 2011-2022 走看看