Go 第16章 sync Go 第16章 sync

2023-09-25

一、Mutex 互斥锁

  • Lock() // 写的时候 排斥其他的写和读锁

  • Unlock()

package main

import (
   "fmt"
   "sync"
   "time"
)

func main() {
   l := &sync.Mutex{}
   go lockFunc(l)
   go lockFunc(l)
   go lockFunc(l)
   go lockFunc(l)
   for {}
}

func lockFunc(lock *sync.Mutex) {
   lock.Lock()
   fmt.Println("疯狂刮痧")
   time.Sleep(time.Second)
   lock.Unlock()
}

我们可以看到输出”疯狂刮痧“是依次打印出来的

二、RWMutex 读写互斥锁

  • Lock() // 写的时候 排斥其他的写和读锁

  • Unlock()

  • Rlock() // 在读取的时候,不会阻其他的读锁,但是会排斥掉写锁

  • Runlock()

package main

import (
   "fmt"
   "sync"
   "time"
)

func main() {
   l := &sync.RWMutex{}
   go lockFunc(l)
   go lockFunc(l)
   go lockFunc(l)
   go lockFunc(l)
   for {}
}

func lockFunc(lock *sync.RWMutex) {
   lock.RLock()
   fmt.Println("疯狂刮痧")
   time.Sleep(time.Second)
   lock.RUnlock()
}

我们可以看到输出”疯狂刮痧“是一次打印出来的

三、Once

  • Once.Do(一个函数) 这个方法无论被调用多少次,这里只会执行一次

package main

import (
   "fmt"
   "sync"
)

func main() {
   o := &sync.Once{}
   for i := 1; i <= 10; i++ {
      o.Do(func() {
         fmt.Println(i)
      })
   }
}

四、WaitGroup

  • Add(delta int) 设定需要 Done 多少次

  • Done() Done一次+1

  • Wait() 再到达 Done 的次数前一直阻塞

package main

import (
   "fmt"
   "sync"
   "time"
)

func main() {
   wg := &sync.WaitGroup{}
   wg.Add(2)
   go func() {
      time.Sleep(time.Second)
      wg.Done()
      fmt.Println("1")
   }()
   go func() {
      time.Sleep(2 * time.Second)
      wg.Done()
      fmt.Println("2")
   }()
   wg.Wait()
   fmt.Println("0")
}

五、Map 一个并发字典

  • Store

  • Load

package main

import (
   "fmt"
   "sync"
   "time"
)

func main() {
   m := &sync.Map{}
   go func() {
      for {
         m.Store(1, 1)
      }
   }()
   go func() {
      for {
         fmt.Println(m.Load(1))
      }
   }()
   time.Sleep(100)
}
  • LoadOrStore

  • Delete

package main

import (
   "fmt"
   "sync"
)

func main() {
   m := &sync.Map{}
   m.Store(1, 1)
   m.Delete(1)
   fmt.Println(m.Load(1))
   m.LoadOrStore(1, 1)
   fmt.Println(m.Load(1))
}
  • Range:return true 才会继续往下遍历

package main

import (
   "fmt"
   "sync"
)

func main() {
   m := &sync.Map{}
   m.Store(1, 1)
   m.Store(2, 2)
   m.Range(func(key, value interface{}) bool {
      fmt.Println(key, value)
      return true
   })
}

六、Pool 并发池

  • Put

  • Get

package main

import (
   "fmt"
   "sync"
   "time"
)

func main() {
   p := &sync.Pool{}
   for i := 1; i <= 5; i++ {
      p.Put(i)
   }
   for i := 1; i <= 5; i++ {
      time.Sleep(time.Second)
      fmt.Println(p.Get())
   }
}

七、Cond 没多大用的通知解锁

  • NewCond (lock) 创建一个 cond

  • co.L.Lock()

    • co.L.Unlock0

    • 创建一个锁区间,在区域内部都可以 co.wait()

  • co.Broadcast() 解锁全部

package main

import (
   "fmt"
   "sync"
   "time"
)

func main() {
   co := sync.NewCond(&sync.Mutex{})
   flag := false
   go func() {
      co.L.Lock()
      fmt.Println("lock1")
      for flag {
         co.Wait()
      }
      fmt.Println("unlock1")
      co.L.Unlock()
   }()
   go func() {
      co.L.Lock()
      fmt.Println("lock2")
      for flag {
         co.Wait()
      }
      fmt.Println("unlock2")
      co.L.Unlock()
   }()
   co.Broadcast()
   time.Sleep(time.Second)
}
  • co.Signal() 解锁一个

package main

import (
   "fmt"
   "sync"
   "time"
)

func main() {
   co := sync.NewCond(&sync.Mutex{})
   flag := false
   go func() {
      co.L.Lock()
      fmt.Println("lock1")
      for flag {
         co.Wait()
      }
      fmt.Println("unlock1")
      co.L.Unlock()
   }()
   go func() {
      co.L.Lock()
      fmt.Println("lock2")
      for flag {
         co.Wait()
      }
      fmt.Println("unlock2")
      co.L.Unlock()
   }()
   time.Sleep(time.Second)
   co.Signal()
   time.Sleep(time.Second)
   co.Signal()
}
阅读 337