每日一个 Golang Packages 06/11 sync

2020/06/11

package main
import (
    "fmt"
    "math/rand" 
    "sync" 
    "time"
)

var ticket int = 10
var mutex sync.Mutex // 创建互斥锁
var wg sync.WaitGroup // 创建同步等待组
var rwMutex sync.RWMutex // 创建读写锁

func main() {
  wg.Add(7)
  // 临界资源问题,会出现超卖的现象 (互斥锁)
  go getRich("脱贫机会1")
  go getRich("脱贫机会2")
  go getRich("脱贫机会3")

  // 读写锁
  go writeData(1)
  go readData(1)
  go writeData(2)
  go readData(2)

  wg.Wait() // main 等待

  fmt.Println("程序结束")
}

func getRich(task string) {
    rand.Seed(time.Now().UnixNano()) // 生成随机数量
    defer wg.Done()

    for {
        mutex.Lock() // 上锁之后,只能有一个 goroutine 执行
        if ticket > 0 {
            time.Sleep(time.Duration(rand.Intn(1000)) * time.Microsecond)
            fmt.Println("脱贫人口在减少:", ticket)
            ticket--
        } else {
            mutex.Unlock() // 解锁
            fmt.Println(task, "用完了,你注定是穷人了!")
            break
        }
        mutex.Unlock() // 使用互斥锁的时候操作结束之后,一定要解锁
    }
}

// 可以多个 goroutine 同时读
func readData(i int) {
    defer wg.Done()

    fmt.Println(i, "read start ...")
    rwMutex.RLock() // 读操作上锁
    fmt.Println(i, "reading...")
    time.Sleep(3 * time.Second)
    rwMutex.RUnlock() // 读操作解锁
    fmt.Println(i, "read over ...")
}

// 写的时候加锁,不能读也不能写
func writeData(i int) {
    defer wg.Done()

    fmt.Println(i, "write start ...")
    rwMutex.Lock()
    fmt.Println(i, "writing ...")
    time.Sleep(3 * time.Second)
    rwMutex.Unlock() // 写操作解锁
    fmt.Println(i, "write over ...")
}

顺便佛系一下用 go 做做 leetcode 的练习题同步到了 GitHub 大家也可以看看。

一步一个脚印,稳扎稳打,重新出发!从基本的 Golang Packages 记忆开始,坚持 ing!

本作品采用《CC 协议》,转载必须注明作者和本文链接
微信搜索:上帝喜爱笨人
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!