使用 sync.Cond 来协调并发 goroutine 的访问共享资源
2023-11-28 09:33:25 软件 207观看
摘要使用 sync.Cond 解决并发访问共享资源问题在并发编程中,当多个 goroutine 需要访问共享资源时,我们需要使用一些机制来协调它们的执行顺序,以避免竞态条件和数据不一致的问题。在 Go 语言中,sync.Cond 条件变量就是一种常

使用 sync.Cond 解决并发访问共享资源问题

在并发编程中,当多个 goroutine 需要访问共享资源时,我们需要使用一些机制来协调它们的执行顺序,以避免竞态条件和数据不一致的问题。在 Go 语言中,sync.Cond 条件变量就是一种常用的机制,它可以用来等待和通知其他 goroutine。AfN28资讯网——每日最新资讯28at.com

sync.Cond 和互斥锁的区别

互斥锁(sync.Mutex)用于保护临界区和共享资源,而 sync.Cond 则用于协调多个 goroutine 的执行顺序。互斥锁只能一个 goroutine 持有锁,其他 goroutine 必须等待锁被释放才能继续执行。而 sync.Cond 可以让等待的 goroutine 在条件满足时被唤醒,进而继续执行。AfN28资讯网——每日最新资讯28at.com

sync.Cond 的四个方法

sync.Cond 的定义如下:AfN28资讯网——每日最新资讯28at.com

// Each Cond has an associated Locker L (often a *Mutex or *RWMutex),// which must be held when changing the condition and// when calling the Wait method.//// A Cond must not be copied after first use.type Cond struct {        noCopy noCopy        // L is held while observing or changing the condition        L Locker        notify  notifyList        checker copyChecker}

每个 Cond 实例都会关联一个锁 L(互斥锁 *Mutex,或读写锁 *RWMutex),当修改条件或者调用 Wait 方法时,必须加锁。AfN28资讯网——每日最新资讯28at.com

1. NewCond 创建实例

func NewCond(l Locker) *Cond

NewCond 方法用于创建一个 Cond 实例,并关联一个锁(互斥锁或读写锁)。AfN28资讯网——每日最新资讯28at.com

2. Broadcast 广播唤醒所有等待的 goroutine

// Broadcast wakes all goroutines waiting on c.//// It is allowed but not required for the caller to hold c.L// during the call.func (c *Cond) Broadcast()

Broadcast 方法用于唤醒所有等待条件变量 c 的 goroutine。它不需要持有锁来调用。AfN28资讯网——每日最新资讯28at.com

3. Signal 唤醒一个等待的 goroutine

// Signal wakes one goroutine waiting on c, if there is any.//// It is allowed but not required for the caller to hold c.L// during the call.func (c *Cond) Signal()

Signal 方法用于唤醒一个等待条件变量 c 的 goroutine。它不需要持有锁来调用。AfN28资讯网——每日最新资讯28at.com

4. Wait 等待条件变量满足

// Wait atomically unlocks c.L and suspends execution// of the calling goroutine. After later resuming execution,// Wait locks c.L before returning. Unlike in other systems,// Wait cannot return unless awoken by Broadcast or Signal.//// Because c.L is not locked when Wait first resumes, the caller// typically cannot assume that the condition is true when// Wait returns. Instead, the caller should Wait in a loop:////    c.L.Lock()//    for !condition() {//        c.Wait()//    }//    ... make use of condition ...//    c.L.Unlock()//func (c *Cond) Wait()

Wait 方法会自动释放锁,并挂起当前的 goroutine,直到条件变量 c 被 Broadcast 或 Signal 唤醒。被唤醒后,Wait 方法会重新获得锁,并继续执行后续的代码。AfN28资讯网——每日最新资讯28at.com

使用示例

下面是一个使用 sync.Cond 的示例,实现了一个简单的读写同步机制:AfN28资讯网——每日最新资讯28at.com

package mainimport (    "fmt"    "sync"    "time")var done = falsefunc read(str string, c *sync.Cond) {    c.L.Lock()    for !done {        c.Wait()    }    fmt.Println(str, "start reading")    c.L.Unlock()}func write(str string, c *sync.Cond) {    fmt.Println(str, "start writing")    time.Sleep(2 * time.Second)    c.L.Lock()    done = true    c.L.Unlock()    fmt.Println(str, "wake up all")    c.Broadcast()}func main() {    m := &sync.Mutex{}    c := sync.NewCond(m)    go read("reader1", c)    go read("reader2", c)    write("writer", c)    time.Sleep(5 * time.Second)}

在这个示例中,有两个读取协程(reader1 和 reader2)和一个写入协程(writer)。写入协程在执行后会通知所有等待的读取协程,读取协程在条件满足时才能开始读取。AfN28资讯网——每日最新资讯28at.com

输出结果如下:AfN28资讯网——每日最新资讯28at.com

writer start writingwriter wake up allreader2 start readingreader1 start reading

通过使用 sync.Cond,我们可以很方便地实现多个 goroutine 之间的等待和通知机制,从而更好地协调并发访问共享资源的执行顺序。AfN28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-34582-0.html使用 sync.Cond 来协调并发 goroutine 的访问共享资源

声明:本网页内容旨在传播知识,不代表本站观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。

显示全文

上一篇:如何高效地使用Goroutine,你学会了?

下一篇:Spring到底是如何解决循环依赖问题的?​

最新热点