dongsong4418 2018-05-26 12: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 13: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.

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

报告相同问题?

悬赏问题

  • ¥15 安装svn网络有问题怎么办
  • ¥15 Python爬取指定微博话题下的内容,保存为txt
  • ¥15 vue2登录调用后端接口如何实现
  • ¥65 永磁型步进电机PID算法
  • ¥15 sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?
  • ¥88 找成都本地经验丰富懂小程序开发的技术大咖
  • ¥15 如何处理复杂数据表格的除法运算
  • ¥15 如何用stc8h1k08的片子做485数据透传的功能?(关键词-串口)
  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥15 latex怎么处理论文引理引用参考文献