为什么通道会受到互斥量的影响?

Why is the channel affected by mutex?

我不知道为什么 c <- i 在使用互斥量时起作用。

因为second()函数的第一行有rwMutex.Lock()

如果mutex在通道中不工作,则无法理解以下输出值。
输出值从 1 开始排序。

  1. 执行go second(...)
  2. 执行rwMutex.Lock()
  3. 所以c <- i不是运行因为写入被锁定了!
  4. num := <-c 正在工作。

main.go

var (
    dataSendChannel = make(chan int)
    rwMutex         = new(sync.RWMutex)
)

func main() {
    go first(dataSendChannel)
    time.Sleep(time.Second * 100)
}

func first(c chan<- int) {
    for i := 1; i <= 10; i++ {
        go second(dataSendChannel)
        c <- i
    }
}

func second(c <-chan int) {
    rwMutex.Lock()
    num := <-c
    time.Sleep(time.Duration(10-num) * time.Second)
    fmt.Println("[NUM] : ", num)
    rwMutex.Unlock()
}

输出

[NUM] :  1
[NUM] :  2
[NUM] :  3
[NUM] :  4
[NUM] :  5
[NUM] :  6
[NUM] :  7
[NUM] :  8
[NUM] :  9
[NUM] :  10

这是不用时的输出值mutex .

main.go

func second(c <-chan int) {
    num := <-c
    time.Sleep(time.Duration(10-num) * time.Second)
    fmt.Println("[NUM] : ", num)
}

输出

[NUM] :  10
[NUM] :  9
[NUM] :  8
[NUM] :  7
[NUM] :  6
[NUM] :  5
[NUM] :  4
[NUM] :  3
[NUM] :  2
[NUM] :  1

通道上收到一个数据后互斥量是否起作用?

当您使用互斥体锁定变量 num 时,您将阻止后续的 goroutines 锁定互斥体,因为它尚未解锁。

因此,第二个 goroutine 真正等到第一个 goroutine 完成休眠(9 秒),然后打印数字 1。只有在那一刻,第二个 goroutine 才能锁定互斥锁并写入变量 num , 但第三个还不能访问,所以它再次等待,直到第二个 goroutine 打印数字等等。

没有mutex,第一个goroutine休眠时间最长,不会阻止其他人执行和写入num,所以它打印最新的,其他人可以先做他们的工作,因为睡眠较少时间,完成得更快。

如果删除睡眠,两种情况下效果相同。

package main

import (
    "fmt"
    "sync"
    "time"
)

var (
    dataSendChannel = make(chan int)
    rwMutex         = new(sync.RWMutex)
)

func main() {
    go first(dataSendChannel)
    time.Sleep(time.Second * 100)
}

func first(c chan<- int) {
    for i := 1; i <= 10; i++ {
        go second(dataSendChannel)
        c <- i
    }
}

func second(c <-chan int) {
    rwMutex.Lock()
    num := <-c
    fmt.Println("[NUM] : ", num)
    rwMutex.Unlock()
}