golang

Go 使用 sync.cond 来通知一组等待协程

2023-02-17  本文已影响0人  三梦哥

当遇到一个协程写,其它协程处于等待读取的时候场景的时候,需要使用标准库中的sync.cond才能优雅的解决。

package main

import (
    "log"
    "net/http"
    "sync"
)

type Notifier struct {
    m    map[string]string
    cond *sync.Cond
}

func NewNotifier(m map[string]string) *Notifier {
    return &Notifier{
        m:    m,
        cond: sync.NewCond(&sync.Mutex{}),
    }
}

func listen(index int, name string, notifier *Notifier) {
    v := notifier.m[name]
    for {
        notifier.cond.L.Lock()
        for v == notifier.m[name] {
            notifier.cond.Wait()
        }
        v = notifier.m[name]
        log.Printf("index:%d received %s changed:%s", index, name, v)
        notifier.cond.L.Unlock()
    }
}

func broadcast(name string, value string, notifier *Notifier) {
    notifier.cond.L.Lock()
    notifier.m[name] = value
    notifier.cond.L.Unlock()
    notifier.cond.Broadcast()
}

func main() {
    m := map[string]string{}
    name := "time"
    n := NewNotifier(m)
    for i := -1; i < 3; i++ {
        i := i
        go func() {
            listen(i, name, n)
        }()
    }
    http.HandleFunc("/test", func(writer http.ResponseWriter, request *http.Request) {
        time := request.URL.Query().Get("time")
        broadcast(name, time, n)
    })
    http.ListenAndServe(":8090", nil)
}

当通过浏览器访问http://localhost:8090/test?time=33时候,会触发listen写入协程,然后会通过broadcast来通过其它等待的协程。
通过更换time的值,可以看到,我们期望的是当time 的值相比之前发生变化的时候,才能看到日志输出。

上一篇下一篇

猜你喜欢

热点阅读