首页  >  文章  >  后端开发  >  使用sync.Cond进行条件等待时如何避免竞争条件?

使用sync.Cond进行条件等待时如何避免竞争条件?

Susan Sarandon
Susan Sarandon原创
2024-11-10 14:21:02866浏览

How to Avoid Race Conditions When Using sync.Cond for Conditional Waiting?

正确使用sync.Cond进行条件等待

在探索sync.Cond的功能时,很明显可能会出现竞争条件锁定sync.Mutex 和调用cond.Wait 之间。为了证明这一点,在主 Goroutine 中引入了人为延迟,模拟竞争条件:

package main

import (
    "sync"
    "time"
)

func main() {
    var m sync.Mutex
    var c = sync.NewCond(&m)

    go func() {
        time.Sleep(1 * time.Second)
        c.Broadcast()
    }()

    m.Lock()
    time.Sleep(2 * time.Second)
    c.Wait()
}

执行此代码会导致死锁恐慌,因为 goroutine 正在等待尚未发出信号的条件.

解决竞争条件

避免这种竞争条件的正确方法是确保在调用 cond.Wait 之前锁定sync.Mutex。这可以防止当前 Goroutine 在等待某个条件时其他 Goroutine 修改共享数据:

package main

import (
    "sync"
    "time"
)

func main() {
    var m sync.Mutex
    var c = sync.NewCond(&m)

    go func() {
        time.Sleep(1 * time.Second)
        m.Lock()
        c.Broadcast()
        m.Unlock()
    }()

    m.Lock()
    c.Wait()
    m.Unlock()
}

替代同步构造

虽然sync.Cond 很有用在多个 goroutine 等待共享资源变得可用的情况下,考虑替代同步原语非常重要。例如,如果编写者和读者之间存在一对一的关系,则sync.Mutex可能足以进行通信:

var sharedRsc = make(map[string]interface{})

func main() {
    m := sync.Mutex{}
    go func() {
        m.Lock()
        sharedRsc["rsc1"] = "foo"
        m.Unlock()
    }()

    m.Lock()
    fmt.Println(sharedRsc["rsc1"])
    m.Unlock()
}

在涉及多个读者的情况下,通道提供了更有效的方式用于传递数据的可扩展解决方案。

以上是使用sync.Cond进行条件等待时如何避免竞争条件?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn