2017-09-15 46 views
-2
package main 

var fooRunning = false 
var barRunning = false 

func foo() { 
    fooRunning = true 
    defer func() { fooRunning = false }() 
    if barRunning { 
     // wait for bar() to finish 
    } 
    ... 
} 

func bar() { 
    barRunning = true 
    defer func() { barRunning = false }() 
    if fooRunning { 
     // wait for foo() to finish 
    } 
    ... 
} 

在我的情況下,如果我們運行go foo()它應該等待bar()完成,反之亦然。什麼是最好的方式來做到這一點?請注意,它們也可以獨立執行。如何等待多個goroutine完成?

+1

相關/可能重複[這個golang代碼有什麼問題?](https://stackoverflow.com/questions/28958192/whats-wrong-with-this-golang-code?noredirect=1&lq=1) – icza

+2

那些要求導致了大量的必須妥善處理的競爭條件(如果其他例程在檢查後立即終止,該怎麼辦?如果有人在否定檢查後立即啓動另一例程,該怎麼辦等等。如果某人運行2個例程foo ())我強烈地敦促你創建一個更好的設計,如果你沒有2個互相依賴另一個獨立運行狀態的例程。 – nos

+1

@nos提到的問題中的代碼具有設計的死鎖。沒有解決方案可以用於給定的場景。 – Adrian

回答

-1

您可以使用頻道!等我從生鏽的去記住,這將給:

func foo() { 
    c := make(chan int) 
    go bar(c) 
    <-c 
} 

和酒吧

func bar(c chan int) { 
    // do stuff here 
    c <- 0 
} 
+0

如果bar()沒有運行?頻道將阻止進一步的執行,對吧? –

+0

是的,除非另一個goroutine在通道中推入一個整數,否則'<-c'將會阻塞,直到給出進一步的整數。如果你忘記在'bar'中給頻道整數,那麼你的程序將會陷入死鎖 –

+1

這隻提供單向阻塞,問題是雙向的;它沒有解決問題中設計的僵局;並且它不必要地使用頻道。 ['sync.WaitGroup'](https://golang.org/pkg/sync/#WaitGroup)正是爲這個用例而構建的,但是直到從設計中刪除死鎖後才能提出解決方案。 – Adrian

0

你的要求不能滿足安全的任何具體設計。按照規定,你說foobar可以在併發例程中運行,並且如果其中一個或兩個都啓動了,另一個應該等待它們都完成。儘管如此,處方太弱了;如果foo開始然後完成,但bar尚未開始運行,會發生什麼情況?如果bar從未運行過,該怎麼辦?或者如果bar運行,但foo從來沒有呢?

您是否要求foobar必須啓動並完成才能使程序正確?如果是這樣,我可以猜想你的意思是什麼:你想要一個barrier等待他們都完成前繼續。

package main 

import (
    "fmt" 
    "sync" 
    "time" 
) 

func foo() { 
    fmt.Println("foo") 
} 

func bar() { 
    fmt.Println("bar") 
} 

func within(wg sync.WaitGroup, f func()) { 
    wg.Add(1) 
    go func() { 
     defer wg.Done() 
     f() 
    }() 
} 

func main() { 
    var wg sync.WaitGroup 
    within(wg, foo) 
    within(wg, bar) 
    wg.Wait() 
    fmt.Println("Both foo and bar completed.") 
} 

That same example in the Playground

注意,在這裏,無論foo也不bar相互瞭解;爲了協調這兩個呼叫,只有他們的呼叫者是。

您原來的嘗試可能導致你做出foobar各關閉了或接受作爲參數sync.WaitGroup,每個函數首先adding itself to the groupwaiting on it退出前的道路。那種方式就是瘋狂。

如果foo啓動並完成bar有機會將自身添加到WaitGroup之前,foobar之前退出,即使你可以聲稱他們已經同時運行,或與bar運行前foo可以積極註冊逆州。再一次,因爲這是你的程序中一個很不明確的方面,所以我建議你把注意力集中在更高層次的障礙上,而不是關注這兩個函數的相互依賴。