为什么我的goroutine饿死了?

时间:2016-04-19 18:04:58

标签: multithreading go concurrency goroutine starvation

概述

我正在编写一个程序,在一个goroutine中启动服务器。 服务器有几个不同的goroutines:

  1. 主要goroutine :它处理初始化,启动第二个goroutine,侦听新连接(2),然后进入无限循环以对从连接(即客户端)接收的数据进行操作)。
  2. listen goroutine :此goroutine进入无限循环,不断监听新连接。如果接受了新连接,则会启动另一个goroutine,它会侦听来自连接的消息,直到它被关闭。
  3. 服务器似乎运行良好。我可以成功添加许多新连接,并且在服务器最初接受这些新连接后,我也可以发送这些新连接的数据。

    我的客户端非常简单。还有两个goroutines:

    1. 主要goroutine :它处理初始化,向服务器注册客户端,启动第二个goroutine以从服务器读取数据(2),然后进入无限循环以对其执行操作从服务器收到的数据。
    2. 第二个goroutine :此goroutine不断尝试从服务器读取数据,直到连接关闭。
    3. 饥饿

      我在客户端遇到了巨大的饥饿问题。具体来说,客户的第二个goroutine总是挨饿。以下是goroutine挨饿的来源:

      func receiver() {
          for {
              msg, err := bufio.NewReader(conn).ReadString(byte(protocol.EndOfMessage))
              if err != nil {
                  fmt.Printf("Disconnected from server %v.\n", conn.RemoteAddr())
                  return
              }
              if len(msg) < 2 {
                  continue
              }
              receiverToHandler <- msg[1 : len(msg)-1]
          }
      }
      

      我确信正在从服务器向客户端发送消息。我也确定发送的邮件以protocol.EndOfMessage结尾。我也确定我从服务器获取数据的方法是正确的,因为我使用相同的代码来注册客户端,而不是在无限循环中运行它我允许它预先指定的尝试次数。

      出于某种原因,我的客户不会收到数据。

      如果我用以下代码替换上面的代码,请确保我不会误解goroutines的性质:

      func receiver() {
          for {
              fmt.Println("In the receiver goroutine!")
          }
      }
      

      goroutine完全符合预期:一切都像以前一样完成,但是&#34;在接收器goroutine!&#34;不断印刷。因此,在这种情况下,例程肯定正确执行。

      我的处理程序

      func handleMessage(debug bool) {
          select {
          case msg := <-receiverToHandler:
              update(msg, debug)
          default:
              /* if debug {
               *     fmt.Printf("Nothing received!\n")
               * }
               */
          }
      }
      

      目前,update(msg, debug)只是致电fmt.Println(msg)

      我能做些什么来干净地解决这个问题吗?我觉得放弃优先级/强制调度程序运行是解决这个问题的一个hacky解决方案。

0 个答案:

没有答案