2012-04-14 6 views
7

Aptalca basit bir iş parçacığı alıştırması olarak, sleeping barber problem ürününü golang içinde uygulamaya çalışıyorum. Kanallarla bu oldukça kolay olmalı, ama heisenbug'le karşılaştım. Yani, teşhis etmeye çalıştığımda sorun ortadan kalkıyor! Aşağıdakileri göz önünde bulundurun. main() işlevi, tam sayıları (veya "müşterileri") shop kanalına iter. barber(), "müşterilerin" saçını kesmek için shop kanalını okur. fmt.Print ifadesini customer() işlevine eklerseniz, program beklendiği gibi çalışır. Aksi halde, barber() hiç kimsenin saçını kesmez.Stdout'a yazdırmak, engellenmiş goroutine neden oluyor?

package main 

import "fmt" 

func customer(id int, shop chan<- int) { 
    // Enter shop if seats available, otherwise leave 
    // fmt.Println("Uncomment this line and the program works") 
    if len(shop) < cap(shop) { 
     shop <- id 
    } 
} 

func barber(shop <-chan int) { 
    // Cut hair of anyone who enters the shop 
    for { 
     fmt.Println("Barber cuts hair of customer", <-shop) 
    } 
} 

func main() { 
    shop := make(chan int, 5) // five seats available 
    go barber(shop) 
    for i := 0; ; i++ { 
     customer(i, shop) 
    } 
} 

Neyin hakkında bir fikriniz var mı?

cevap

5

Sorun, Go programlayıcısının uygulandığı yoldur. Mevcut goroutin, yalnızca bir sistem çağrısı veya bir engelleme kanalı işlemi gerçekleştirdiğinde diğer goroutine yol açabilir. fmt.Println bir sistem çağrısı yaparak, goroutine verim fırsatı verir. Aksi halde bir tane yoktur. Pratikte bu çoğu zaman önemli değildir, ancak bunun gibi küçük problemler için bazen parçalanabilir. Ayrıca

, bir bir kanalda göndermek olduğunu engellenmeyen yapmanın daha deyimsel, az açık saçık yol: berberin

func customer(id int, shop chan<- int) { 
    // Enter shop if seats available, otherwise leave 
    select { 
    case shop <- id: 
    default: 
    } 
} 

bunu yaparsınız yolu, bir müşteri bitebileceğini bekleyen dışında Bu zamana kadar alışveriş yaptığınız zamandan beri, len(shop) değişmiş olabilir.

+1

Git, çalışma zamanı tarafından yalnızca bir iş parçacığı kullanılıyorsa, yanıtınız bekler. GOMAXPROCS'yi ya lazy1 gibi çalışma zamanı çağrısı aracılığıyla ayarlama ya da ortam değişkenini ayarlama, herhangi bir goroutinin ayrı bir iş parçacığı üzerinde diğer goroutine paralel olarak çalışmasına da izin verecektir. Cevabınızı, çalışma süresinin, mevcut iş parçacıklarındaki goroutleri nasıl çoğalttığını yansıtacak şekilde genişletmek faydalı olabilir. –

1

Ana çözmelerin başında runtime.GOMAXPROCS(2) ekleniyor mu?

+0

Aslında, öyle. Tek çekirdekli makinemde bile ... – Jjed

+0

Düzeltse bile, doğru yaklaşım değildir. –

+0

@MattJoiner Ayrıntı yapabilir misiniz? – lazy1

İlgili konular