goroutines死锁,需要一些解释

时间:2018-02-04 05:21:44

标签: go deadlock goroutine

我想了解Go例程如何在这里工作。

问题1: go例程是否继承了GO主例程/ func ??

中的任何内容

问题2: 还想知道我是否发送了" hi whats up"进入msg频道为什么在LINE:13 ????

的go-routine没有收到它
  1 package main
  2 
  3 import "fmt"
  4 
  5 func main() {
  6     msg := make(chan string, 2) //channel (bidirectional channel) of type string
  7 
  8     msg <- "hi whats up"
  9     fmt.Println("*****I am main go routine*****")
 10 
 11     go func() {
 12         fmt.Println("*****HI ABHI *****\n")
 13         temp := <-msg
 14         fmt.Println(temp)
 15         msg <- "Hello from a goroutine!" //send a string through the channel
 16     }()
 17 
 18     fmt.Println("Main routine waiting for message")
 19 
 20     fmt.Println(<-msg) //receive the string from the channel
 21     fmt.Println(<-msg)
 22 }  

获取以下错误:

  

*****我主要做常规*****

     

等待消息的主要例程

     

你好吗

     

***** HI ABHI *****

     

致命错误:所有goroutine都睡着了 - 死锁!

     

goroutine 1 [陈接收]:

     

main.main()

     

/Users//work/go/src/github.com/Golang_play/goroutine/goroutine.go:21   + 0x1e6

     

goroutine 5 [陈接收]:

     

main.main.func1(0xc420054060)

     

/Users/work/go/src/github.com/Golang_play/goroutine/goroutine.go:13   由main.main创建的+ 0x98 /Users/work/go/src/github.com/Golang_play/goroutine/goroutine.go:11   + 0xe2退出状态2

同样在以下程序中,LINE 14从不打印。

 5 func main() {
  6     msg := make(chan string, 2) //channel (bidirectional channel) of type string
  7 
  8     msg <- "hi whats up"
  9     fmt.Println("*****I am main go routine*****")
 10 
 11     go func() {
 12         fmt.Println("*****HI ABHI *****\n")
 13         temp := <-msg
 14         fmt.Println(temp)
 15         //msg <- "Hello from a goroutine!" //send a string through the channel
 16     }()

3 个答案:

答案 0 :(得分:3)

您尝试在同一频道上以两种方式发送消息,并且您没有做任何事情来保证谁阅读哪些消息。在func goroutine尝试从频道中读取之前,主goroutine完全可以接收它发送的消息。如果发生这种情况,两个goroutines都会等待永远不会到达的消息。

使用两个频道。

答案 1 :(得分:1)

新启动的goroutine可以通过闭包从外部代码中捕获变量,但不会继承任何内容。

第13行的通道接收与第20行的通道之间存在竞争。如果第20行的读取首先执行,它将消耗通道上的唯一值,最终,两个goroutine都被阻止读取一个通道,因此死锁错误。如果你想从goroutine中获取一个值,那么最好有另一个通道,而不是试图对它进行排序。

答案 2 :(得分:1)

这是一个有效的例子:

const complexX1Key = {complexKey:"x1"};//object key x1
const org = [
  [
    [complexX1Key/* reference to x1 */,{complexValue:"a1"}],
    [{complexKey:"x2"},{complexValue:"a2"}],
    [{complexKey:"x3"},{complexValue:"a3"}]
  ],[
    [{complexKey:"x4"},{complexValue:"b1"}],
    [complexX1Key/* reference to x1 */,{complexValue:"b2"}],
    [{complexKey:"x5"},{complexValue:"b3"}]
  ]
];
const toDygraph = org => {
  const flatten = twoDArray =>
  twoDArray.reduce(
    (all,item)=>
      all.concat(item),
    []
  );
  //get all keys (org[i][0])
  const allKeys = flatten(org)
    .map(([key])=>key)
    .filter((x,index,all)=>all.indexOf(x)===index);//remove double keys
  const result = 
    org//for each [[key:value],[key:value]]
    .reduce(
      (arr,keyValues)=>{//keyValues is [[key,value],[key,value]]
        allKeys.forEach(//for every key in all keys
          key=>{
            //find an item [key,value] in current value set that has key
            //  of current key in all keys
            const val = keyValues.find(([x])=>x===key);
            //find in arr (arr is [[key],[key],[key]])
            arr.find(([x])=>x===key)
            //add the found value ([key,value]) to this [key] or add null if not found
            .push((val&&val[1])||null);
          }
        )
        return arr;
      },
      allKeys.reduce(//create an array of [[key1],[key2],[key3]]
        (all,key)=>
          all.concat([[key]]),
        []
      )
    );
  return result;
}

console.log(
  JSON.stringify(toDygraph(org),undefined,2)
);

对于无缓冲的通道,消息传递是同步的,因此goroutines永远不会从它们自己接收消息(因为相同的goroutine必须同时发送和接收才能发生这种情况)。请注意,此设计要求您在写入任何内容之前从package main import "fmt" func main() { msg := make(chan string) go func() { temp := <-msg fmt.Println(temp) msg <- "Hello from a goroutine!" }() msg <- "hi whats up" fmt.Println(<-msg) } 频道开始goroutine阅读,否则您将无法等待阅读器而无法启动它。