dongsong4418 2018-05-26 04:54
浏览 25
已采纳

这些goroutines为什么不阻止?

I expect these two goroutines to block forever for the reasons as below but it doesn't. Why?

  1. The channel has no buffer and will be waiting for receive() to receive.

  2. send() hold the lock so num := <-s.ch in receive() has no chance to execute.

  3. Block forever

What's wrong?

package main

import (
    "sync"
    "fmt"
)

type S struct {
    mu sync.Mutex
    ch chan int
    wg sync.WaitGroup
}

func (s *S) send() {
    s.mu.Lock()
    s.ch <- 5
    s.mu.Unlock()
    s.wg.Done()
}
func (s *S) receive() {
    num := <-s.ch
    fmt.Printf("%d
", num)
    s.wg.Done()
}

func main() {
    s := new(S)
    s.ch = make(chan int)
    s.wg.Add(2)
    go s.send()
    go s.receive()
    s.wg.Wait()
}

展开全部

  • 写回答

1条回答 默认 最新

  • dsfds656545 2018-05-26 05:01
    关注

    Your receive() method doesn't use the lock, so send() holding the lock has no effect on receive().

    And since both send() and receive() run in their own goroutine, send() will make it to the point where it sends the value 5 on the channel, and so the receive in receive() can proceed, and it will, and will print it in the next line.

    Also note that to use channels from multiple goroutines, you do not need "external" synchronization. Channels are safe for concurrent use, data races cannot occur by design. For details, see If I am using channels properly should I need to use mutexes?

    If the receive() method would also use the lock like this:

    func (s *S) receive() {
        s.mu.Lock()
        num := <-s.ch
        s.mu.Unlock()
        fmt.Printf("%d
    ", num)
    }
    

    Then yes, nothing would be printed, because the receive cannot happen until send() releases the lock, but that can't happen until someone receives from the channel.

    And in this case the program would terminate after 1 second without printing anything, because when the sleep is over the main goroutine ends, so does your whole app with it. It does not wait for other non-main goroutines to complete. For details, see No output from goroutine in Go.

    Edit:

    Yes, you misunderstand the lock. Locking a sync.Mutex only locks the mutex value itself, it does not lock the whole struct value (it can't). And "locks the value itself" means if another goroutine also calls its Mutex.Lock() method, that call will block until the lock is released by calling its Mutex.Unlock() method. When it's unlocked, the goroutine that is blocked at the Mutex.Lock() call will proceed to lock the mutex and return.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
编辑
预览

报告相同问题?

手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部