2014-11-14 17 views
10

कोड हार्ड कोडित JSON डेटा के साथ ठीक काम करता है फिर भी काम नहीं करता है जब मैं एक फ़ाइल से JSON डेटा पढ़ें। sync.WaitGroup का उपयोग करते समय मुझे fatal error: all goroutines are asleep - deadlock त्रुटि मिल रही है।GO भाषा: गंभीर त्रुटि: सभी goroutines सो रहे - गतिरोध नीचे

श्रमजीवी उदाहरण के साथ हार्ड-कोडेड JSON डेटा:

package main 

import (
    "bytes" 
    "fmt" 
    "os/exec" 
    "time" 
) 

func connect(host string) { 
    cmd := exec.Command("ssh", host, "uptime") 
    var out bytes.Buffer 
    cmd.Stdout = &out 
    err := cmd.Run() 
    if err != nil { 
     fmt.Println(err) 
    } 
    fmt.Printf("%s: %q\n", host, out.String()) 
    time.Sleep(time.Second * 2) 
    fmt.Printf("%s: DONE\n", host) 
} 

func listener(c chan string) { 
    for { 
     host := <-c 
     go connect(host) 
    } 
} 

func main() { 
    hosts := [2]string{"[email protected]", "[email protected]"} 
    var c chan string = make(chan string) 
    go listener(c) 

    for i := 0; i < len(hosts); i++ { 
     c <- hosts[i] 
    } 
    var input string 
    fmt.Scanln(&input) 
} 

उत्पादन:

[email protected]user-VirtualBox:~/go$ go run channel.go 
[email protected]: " 09:46:40 up 86 days, 18:16, 0 users, load average: 5" 
[email protected]: " 09:46:40 up 86 days, 17:27, 1 user, load average: 9" 
[email protected]: DONE 
[email protected]: DONE 

नहीं काम - पढ़ना JSON डेटा फ़ाइल के साथ उदाहरण:

आउटपुट

[email protected]:~/go$ go run deploy.go < hosts.txt 
[email protected]: " 09:46:40 up 86 days, 18:16, 0 users, load average: 5" 
[email protected]: " 09:46:40 up 86 days, 17:27, 1 user, load average: 9" 
[email protected] : DONE 
[email protected]: DONE 
fatal error: all goroutines are asleep - deadlock! 

goroutine 1 [semacquire]: 
sync.runtime_Semacquire(0xc210000068) 
    /usr/lib/go/src/pkg/runtime/sema.goc:199 +0x30 
sync.(*WaitGroup).Wait(0xc210047020) 
    /usr/lib/go/src/pkg/sync/waitgroup.go:127 +0x14b 
main.main() 
    /home/user/go/deploy.go:64 +0x45a 

goroutine 3 [chan receive]: 
main.listener(0xc210038060) 
    /home/user/go/deploy.go:28 +0x30 
created by main.main 
    /home/user/go/deploy.go:53 +0x30b 
exit status 2 
[email protected]:~/go$ 

HOSTS.TXT

[ 
    { 
     "username":"user1", 
     "ip":"111.79.154.111" 
    }, 
    { 
     "username":"user2", 
     "ip":"111.79.190.222" 
    } 
] 

उत्तर

27

जाओ कार्यक्रम समाप्त होता है जब मुख्य कार्य समाप्त होता है।

language specification

Program execution begins by initializing the main package and then invoking the function main. When that function invocation returns, the program exits. It does not wait for other (non-main) goroutines to complete.

से इसलिए, आप अपने goroutines समाप्त होने की प्रतीक्षा की जरूरत है। इसके लिए सामान्य समाधान sync.WaitGroup ऑब्जेक्ट का उपयोग करना है।

सरल संभव कोड goroutine सिंक्रनाइज़ करने के लिए:

package main 

import "fmt" 
import "sync" 

var wg sync.WaitGroup // 1 

func routine() { 
    defer wg.Done() // 3 
    fmt.Println("routine finished") 
} 

func main() { 
    wg.Add(1) // 2 
    go routine() // * 
    wg.Wait() // 4 
    fmt.Println("main finished") 
} 

और निष्पादन के क्रम में सिंक्रनाइज़ करने के लिए कई goroutines

package main 

import "fmt" 
import "sync" 

var wg sync.WaitGroup // 1 

func routine(i int) { 
    defer wg.Done() // 3 
    fmt.Printf("routine %v finished\n", i) 
} 

func main() { 
    for i := 0; i < 10; i++ { 
     wg.Add(1) // 2 
     go routine(i) // * 
    } 
    wg.Wait() // 4 
    fmt.Println("main finished") 
} 

WaitGroup उपयोग के लिए।

  1. वैश्विक चर की घोषणा। इसे वैश्विक बनाना इसे सभी कार्यों और विधियों के लिए दृश्यमान करने का सबसे आसान तरीका है।
  2. काउंटर बढ़ाने से। यह मुख्य goroutine से किया जाना चाहिए कोई गारंटी नहीं कि हाल में शुरू कर दिया goroutine स्मृति मॉडल guarantees की वजह से 4 से पहले निष्पादित करेंगे क्योंकि वहाँ।
  3. काउंटर घटाना। यह goroutine के बाहर निकलने पर किया जाना चाहिए। स्थगित कॉल का उपयोग करके, हम सुनिश्चित करते हैं कि यह be called whenever function ends कोई फर्क नहीं पड़ता, लेकिन इससे कोई फर्क नहीं पड़ता कि यह कैसे समाप्त होता है।
  4. काउंटर के लिए प्रतीक्षा कर रहा है 0. यह तक पहुँचने के लिए प्रोग्राम से बाहर निकलने को रोकने के लिए मुख्य goroutine में किया जाना चाहिए।

* वास्तविक पैरामीटर evaluated before starting new gouroutine हैं। इस प्रकार wg.Add(1) से पहले स्पष्ट रूप से उनका मूल्यांकन करने की आवश्यकता है ताकि संभावित रूप से घबराहट कोड काउंटर में वृद्धि न करे।

उपयोग

बजाय

wg.Add(1) 
go g(f(x)) 
+0

मैं GO उपयोग कर रहे हैं के बाद से कल (यहां तक ​​कि एक दिन से भी कम) इसलिए मैं वास्तव में ज्यादा पता नहीं है, हालांकि मैं गया है पढ़ रहा डॉक्टर उपरोक्त कोड अध्ययन/अभ्यास के 1 दिन का परिणाम है। मैं वास्तव में कहाँ सोता हूँ? मैंने उदाहरण में देखा। – BentCoder

+0

@inanzzz पहले जवाब को देखो। –

+0

मुझे लगता है कि मैं गलत स्थानों में बातें डाल रहा हूं। 'घातक त्रुटि: सभी goroutines सो रहे - कम से कम लेकिन वहाँ है गतिरोध' – BentCoder

3

बहुत अच्छी और विस्तृत विवरण Grzegorz zur के लिए धन्यवाद। एक बात है कि मैं इसे बाहर बात करने के लिए है कि आम तौर समारोह अभ्यस्त पिरोया किए जाने की जरूरत है कि मुख्य() में हो चाहते हैं, तो हम कुछ इस तरह होगा:

package main 

import (
    "bufio" 
    "fmt" 
    "io" 
    "io/ioutil" 
    "math/rand" 
    "os" 
    "reflect" 
    "regexp" 
    "strings" 
    "sync" 
    "time" 
) 

var wg sync.WaitGroup // VERY IMP to declare this globally, other wise one //would hit "fatal error: all goroutines are asleep - deadlock!" 

func doSomething(arg1 arg1Type) { 
    // cured cancer 
} 

func main() { 
    r := rand.New(rand.NewSource(time.Now().UnixNano())) 
    randTime := r.Intn(10) 
    wg.Add(1)  
    go doSomething(randTime) 
    wg.Wait() 
    fmt.Println("Waiting for all threads to finish") 
} 

बात यह है कि मैं इसे बाहर बिंदु करना चाहते हैं कि डब्ल्यू जी की वैश्विक declation बहुत महत्वपूर्ण है सभी धागे से पहले खत्म करने के लिए के लिए है मुख्य()

संबंधित मुद्दे