美文网首页
28 goroutine互斥锁

28 goroutine互斥锁

作者: learninginto | 来源:发表于2021-04-12 17:26 被阅读0次
    互斥锁

    互斥锁是传统并发编程中对共享资源进行访问控制的主要手段,它由标准库sync中的Mutex结构体类型表示。sync.Mutex类型只有两个公开的指针方法,Lock和Unlock。Lock锁定当前的共享资源,Unlock进行解锁。

    • demo

    在使用前通过Lock上锁,使用后能过Unlock解锁。

    var count = 0
    var wg sync.WaitGroup
    var mutex sync.Mutex
    
    func test() {
        mutex.Lock()
        count++
        fmt.Println("the count is:", count)
        time.Sleep(time.Millisecond*2)
        mutex.Unlock()
        wg.Done()
    }
    
    func main() {
        for r := 0; r < 20; r++ {
            wg.Add(1)
            go test()
        }
        wg.Wait()
    }
    
    • 通过-race build查看资源竞争,再执行exe对比
    go build -race main.go
    main.exe
    

    发现未加锁之前有报错,协程之间存在竞争关系

    • demo2

    可以关闭下面的互斥锁后,观察它们的变化

    var count = 0
    var wg sync.WaitGroup
    var mutex sync.Mutex
    
    var m = make(map[int]int, 0)
    
    func test(num int) {
        mutex.Lock()
        var sum int = 1
        for i := 1; i <= num; i++ {
            sum *= i
        }
        m[num] = sum
        fmt.Printf("key=%v value=%v\n", num, sum)
        time.Sleep(time.Millisecond * 2)
        mutex.Unlock()
        wg.Done()
    }
    
    func main() {
        for r := 0; r < 40; r++ {
            wg.Add(1)
            go test(r)
        }
        wg.Wait()
    }
    
    读写互斥锁

    读取的时候,可以并发地访问;但写得时候,同一时刻只允许一人操作。

    也就是说,当一个goruntine进行写操作时,其他goruntine既不能进行读操作,也不能进行写操作。

    Go中的读写锁由结构体类型sync.RWMutex表示。它包含了两对方法:一组是对写操作的锁定和解锁,简称“写锁定”和“写解锁”

    func (*RWMutex) Lock()
    func (*RWMutex) Unlock()
    

    另一组表示对读操作的锁定和解锁,简称“读锁定”与“读解锁”

    func (*RWMutex) RLock()
    func (*RWMutex) RUnlock()
    
    • 写操作时互斥,读操作时并行
    var count = 0
    var wg sync.WaitGroup
    var mutex sync.RWMutex
    
    var m = make(map[int]int, 0)
    
    func write(){
        mutex.Lock()
        fmt.Println("执行写操作")
        time.Sleep(time.Second * 2)
        mutex.Unlock()
        wg.Done()
    }
    
    func read(){
        mutex.RLock()
        fmt.Println("执行读操作---")
        //time.Sleep(time.Millisecond * 50)
        mutex.RUnlock()
        wg.Done()
    }
    
    func main() {
        //开启10个协程执行读操作
        for i := 0; i < 10; i++{
            wg.Add(1)
            go write()
        }
        //开启10个协程执行写操作
        for i := 0; i < 10; i++ {
            wg.Add(1)
            go read()
        }
        wg.Wait()
    }
    执行写操作
    //执行读操作---
    //执行读操作---
    //执行读操作---
    //执行读操作---
    //执行读操作---
    //执行读操作---
    //执行读操作---
    //执行读操作---
    //执行读操作---
    //执行读操作---
    //执行写操作
    //执行写操作
    //……
    

    相关文章

      网友评论

          本文标题:28 goroutine互斥锁

          本文链接:https://www.haomeiwen.com/subject/tyixlltx.html