登录
首页 >  Golang >  Go问答

继续出现死锁的情况 - 互斥锁

来源:stackoverflow

时间:2024-02-29 13:00:26 128浏览 收藏

大家好,我们又见面了啊~本文《继续出现死锁的情况 - 互斥锁》的内容中将会涉及到等等。如果你正在学习Golang相关知识,欢迎关注我,以后会给大家带来更多Golang相关文章,希望我们能一起进步!下面就开始本文的正式内容~

问题内容

我正在研究 goroutines 和通道,想知道为什么标题中出现错误。

我的想法是,我有一个全局 int 通道,每次路由都会递增。

通过使用互斥锁,我希望每个例程都会锁定通道,但失败了。

代码在这里:

package main

import (
    "fmt"
    "sync"
)

var number = make(chan int)
var mutex = &sync.Mutex{}

func worker(wg *sync.WaitGroup, id int) {
    defer wg.Done()

    mutex.Lock()
    number <- id + <-number
    mutex.Unlock()
}

func main() {
    var wg sync.WaitGroup
    number <- 0
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go worker(&wg, i)
    }

    wg.Wait()
    fmt.Println(<-number) // expected output: 0+1+2+3+4 = 10
}

https://play.golang.org/p/p5p9bf5zsip


解决方案


这里的问题与您正在使用的通道有关,因为它是无缓冲的。无缓冲的通道将阻塞,直到有接收者接收消息。

这里,主 go 例程向通道添加一个数字,然后创建 5 个 go 例程来取出通道并添加到通道,然后等待它们完成,然后再从通道中取出项目。在有东西从通道接收数字之前,不会向通道添加 0,因此它在到达互斥体之前就会阻塞。

只有当有东西从通道中取出东西时,这 5 个 go 例程才能完成。

如果您通过向 make 调用提供大小来更改为缓冲通道,那么这将开始运行直至完成:

package main

import (
    "fmt"
    "sync"
)

var number = make(chan int, 5)
var mutex = &sync.mutex{}

func worker(wg *sync.waitgroup, id int) {
    defer wg.done()

    mutex.lock()
    number <- id + <-number
    mutex.unlock()
}

func main() {
    var wg sync.waitgroup
    number <- 0
    for i := 0; i < 5; i++ {
        wg.add(1)
        go worker(&wg, i)
    }

    wg.wait()
    fmt.println(<-number) // expected output: 0+1+2+3+4 = 10
}

https://play.golang.org/p/QDXuDH0RGPC

go 中的 channel 用于两个不同 goroutine 之间的同步。 goroutine 会等待读/写,除非它找到另一个对同一通道写/读的 goroutine(假设通道没有缓冲)

这意味着该程序将始终出现死锁:

package main

import (
    "fmt"
)

func main() {
    fmt.Println("Hello, playground")
    done := make(chan bool)
    done <- true
    <- done
}

因为第 10 行会被阻塞,寻找另一个从 chan did 读取的 goroutine,但没有这样的 goroutine。

因此,从同一个 goroutine 进行写入/读取将会阻塞,除非有其他 goroutine 从该通道读取/写入。

以上就是《继续出现死锁的情况 - 互斥锁》的详细内容,更多关于的资料请关注golang学习网公众号!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>