Golang中的select语句可以同时等待互斥锁和通道。

huangapple go评论116阅读模式
英文:

Golang select wait on both a mutex lock and a channel

问题

在Go语言中,可以使用select语句同时等待多个通道。例如:

  1. package main
  2. import "fmt"
  3. func fibonacci(c, quit chan int) {
  4. x, y := 0, 1
  5. for {
  6. select {
  7. case c <- x:
  8. x, y = y, x+y
  9. case <-quit:
  10. fmt.Println("quit")
  11. return
  12. }
  13. }
  14. }
  15. func main() {
  16. c := make(chan int)
  17. quit := make(chan int)
  18. go func() {
  19. for i := 0; i < 10; i++ {
  20. fmt.Println(<-c)
  21. }
  22. quit <- 0
  23. }()
  24. fibonacci(c, quit)
  25. }

(摘自https://go.dev/tour/concurrency/5)

是否有一种机制可以类似地使用互斥锁(mutex lock),在等待通道或互斥锁可用时进行等待?类似这样:

  1. package main
  2. import "fmt"
  3. import "sync"
  4. func fibonacci(c chan int, mu sync.Mutex) {
  5. x, y := 0, 1
  6. for {
  7. select {
  8. case c <- x:
  9. x, y = y, x+y
  10. case mu.Lock():
  11. fmt.Println("locked")
  12. return
  13. }
  14. }
  15. }
  16. func main() {
  17. c := make(chan int)
  18. var mu sync.Mutex
  19. go func() {
  20. for i := 0; i < 10; i++ {
  21. fmt.Println(<-c)
  22. }
  23. mu.Lock()
  24. }()
  25. fibonacci(c, mu)
  26. }

实际的使用场景是,我将一个context传递给一个函数,该函数可能会在互斥锁上等待一段时间,我希望能够通过上下文中止等待。

英文:

In golang it is possible to use a select statement to wait on multiple channels at a time. For example,

  1. package main
  2. import &quot;fmt&quot;
  3. func fibonacci(c, quit chan int) {
  4. x, y := 0, 1
  5. for {
  6. select {
  7. case c &lt;- x:
  8. x, y = y, x+y
  9. case &lt;-quit:
  10. fmt.Println(&quot;quit&quot;)
  11. return
  12. }
  13. }
  14. }
  15. func main() {
  16. c := make(chan int)
  17. quit := make(chan int)
  18. go func() {
  19. for i := 0; i &lt; 10; i++ {
  20. fmt.Println(&lt;-c)
  21. }
  22. quit &lt;- 0
  23. }()
  24. fibonacci(c, quit)
  25. }

(Lifted from https://go.dev/tour/concurrency/5)

Is there any mechanism to do something similar with a mutex lock, where you wait for either a channel or for a mutex lock to become available? Something like:

  1. package main
  2. import &quot;fmt&quot;
  3. import &quot;sync&quot;
  4. func fibonacci(c chan int, mu sync.Mutex) {
  5. x, y := 0, 1
  6. for {
  7. select {
  8. case c &lt;- x:
  9. x, y = y, x+y
  10. case mu.Lock():
  11. fmt.Println(&quot;locked&quot;)
  12. return
  13. }
  14. }
  15. }
  16. func main() {
  17. c := make(chan int)
  18. var mu sync.Mutex
  19. go func() {
  20. for i := 0; i &lt; 10; i++ {
  21. fmt.Println(&lt;-c)
  22. }
  23. mu.Lock()
  24. }()
  25. fibonacci(c, quit, mu)
  26. }

The actual use scenario is that I'm passing in a context to a function that might be waiting on a mutex lock for a while, and I'd like to be able to abort the wait through the context.

答案1

得分: 2

有没有一种机制可以类似于互斥锁,等待通道或互斥锁可用的情况?

没有。

你必须重新设计,例如通过用基于通道的信号量替换互斥锁。

英文:

> Is there any mechanism to do something similar with a mutex lock, where you wait for either a channel or for a mutex lock to become available?

No.

You must redesign, e.g. by replacing the mutex with a channel based semaphore.

huangapple
  • 本文由 发表于 2022年10月1日 14:29:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/73916277.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定