美文网首页
go 如何实现 try-lock?

go 如何实现 try-lock?

作者: wayyyy | 来源:发表于2022-11-13 00:59 被阅读0次

    在某些场景,我们只希望一个任务有单一的执行者,而不像计数器一样,所有的 Goroutine 都成功执行。后续的 Goroutine 在抢锁失败后,需要放弃执行,这时候就需要尝试加锁trylock。

    // Lock try lock
    type Lock struct {
        c chan struct{}
    }
    
    // Lock try lock, return lock result
    func (l Lock) Lock() bool {
        result := false
        select {
        case <-l.c:
            result = true
        default:
        }
        return result
    }
    
    // Unlock the try lock
    func (l Lock) Unlock() {
        l.c <- struct{}{}
    }
    
    // NewLock generate a try lock
    func NewLock() Lock {
        var l Lock
        l.c = make(chan struct{}, 1)
        l.c <- struct{}{}
        return l
    }
    
    func main() {
        var lock = NewLock()
        var wg sync.WaitGroup
        for i := 0; i < 10; i++ {
            wg.Add(1)
            go func() {
                defer wg.Done()
                if !lock.Lock() {
                    println("lock failed")
                    return
                }
                counter++
                println("current counter: ", counter)
                lock.Unlock()
            }()
        }
        wg.Wait()
    }
    

    每个 Goruntine 只有成功执行了 Lock() 才会继续执行后续代码,因此在Unlock() 时可以保证 Lock 结构体里的 Channel 一定是空的,所以不会阻塞也不会失败。

    但要注意 trylock 有时并不是一个好选择,因为大量的 Goruntine 抢锁会无意义地占用 cpu 资源,这就是活锁。活锁指是的程序看起来在正常执行,但 cpu 周期被浪费在抢锁而非执行任务上,从而程序整体的执行效率低下。

    相关文章

      网友评论

          本文标题:go 如何实现 try-lock?

          本文链接:https://www.haomeiwen.com/subject/omjiirtx.html