2011-11-27 25 views
2

我有兩個併發去例程象下面,圍棋編程語言共同併發執行

Routine 1{             

routine procedure 

critical section{              
} 

routine procedure       
} 

Routine 2{             

routine procedure 

critical section{              
} 

routine procedure      
} 

是否有可能通過使用一些去內置功能來實現關鍵部分?

回答

3

你的問題:

我有N個併發去例程(都或多或少相同的目的)。每個人都有一個關鍵部分。在進入臨界區之前,每個例程都會做一些消息發送工作。當它進入關鍵部分時,我需要所有其他例程必須停止執行,直到退出關鍵部分。 GO可以使用任何庫函數嗎?

你在問什麼(在一個goroutine處於關鍵部分時強制停止所有其他goroutine)在Go程序中並不典型。沒有庫函數可以停止所有其他goroutines,因此您需要通過在程序中的goroutine之間設計適當的同步來阻止它們。典型的場景是所有的goroutine(可能)併發運行,除了那些被阻塞的goroutine。

要控制對Go程序中的共享資源的併發訪問,您可以使用Go通道,"sync"程序包,管道或網絡連接。

使用sync.Mutex,轉到代碼可能看起來像這樣(但請記住,只要有可能,圍棋程序最好使用Go渠道,而不是互斥):

package main 

import "sync" 

var m sync.Mutex 
var wg sync.WaitGroup 

func routine1() { 
    ... do something ... 

    m.Lock() 
    ... critical section (access the shared resource here) ... 
    m.Unlock() 

    ... do something ... 
    wg.Done() 
} 

func routine2() { 
    ... do something ... 

    m.Lock() 
    ... critical section (access the shared resource here) ... 
    m.Unlock() 

    ... do something ... 
    wg.Done() 
} 

func main() { 
    wg.Add(1); go routine1() 
    wg.Add(1); go routine2() 
    wg.Wait() 
} 
1

你可以嘗試使用緩衝通道:

c := make(chan int, 2) 

這將緩衝實際發送之前發送的數據。

+0

我已經使用常數BUFSIZE = 10個C:=使(CHAN INT,BUFSIZE)。但是,我想鎖定例程2,直到例程1發送完成。 – Arpssss

+1

嘗試查看標準庫中的同步軟件包。 –

1

你的意思是這樣的嗎?

package main 

import "fmt" 

func ping(recv <-chan int, send chan<- int, end chan<- bool) { 
    fmt.Println("ping") 
    send <- 11 
    send <- 12 
    r1 := <-recv 
    r2 := <-recv 
    fmt.Println("ping", r1, r2) 
    end <- true 
} 

func pong(recv <-chan int, send chan<- int, end chan<- bool) { 
    fmt.Println("pong") 
    r1 := <-recv 
    r2 := <-recv 
    send <- 21 
    send <- 22 
    fmt.Println("pong", r1, r2) 
    end <- true 
} 

func main() { 
    chEnd := make(chan bool) 
    chPing := make(chan int, 2) 
    chPong := make(chan int, 2) 
    go ping(chPing, chPong, chEnd) 
    go pong(chPong, chPing, chEnd) 
    <-chEnd 
    <-chEnd 
    fmt.Println("end") 
} 

輸出:

ping 
pong 
pong 11 12 
ping 21 22 
end 
+0

實際上我有N個例程,每個具有一個臨界區中(爲了簡化它,我使用的發送方法)。現在,是否有可能實施關鍵部分? – Arpssss

+1

如果你有N個程序,是什麼routineM,其中1 <= M <= N,怎麼辦? – peterSO

+0

我有N個併發去程序(都差不多相同的目的)。每個人都有一個關鍵部分。在進入臨界區之前,每個例程都會做一些消息發送工作。當它進入關鍵部分時,我需要所有其他例程必須停止執行,直到退出關鍵部分。 GO可以使用任何庫函數嗎? – Arpssss

1

我不認爲,有在去任何庫來實現的關鍵部分。我認爲Arpssss正在要求一個圖書館。

1

幾種方法是可能的。一個簡單的方法是使用爲完整「事件」鍵入的渠道。

package main 

type int2 struct { 
     a, b int 
} 

func Routine1(tx, rx chan int2) { 
     var x, y int 
     // ... 
     tx <- int2{x, y} 
     // ... 
     z := <- rx // Two rx values in z.a, z.b 
     // ... 
} 

func Routine2(rx, tx chan int2) { 
     var x, y int 
     // ... 
     z := <- rx // Two rx values in z.a, z.b 
     // ... 
     tx <- int2{x, y} 
     // ... 
} 

func main() { 
     // ... 
     tx, rx := make(chan int2), make(chan int2) 
     go Routine1(tx, rx) 
     go Routine2(rx, tx) 
     // ... 
} 
+0

jnml,你說得很對。但是,實際上我的問題是錯誤的。我修改它使其更清楚。 – Arpssss

1

這裏有一個相當於基於通道Atom的解決方案。開始你夠程之前:

doingFileModificationJobs := make(chan bool, 1) 
doingFileModificationJobs <- false 

,然後通過這個通道作爲參數,當你啓動夠程。請注意,只有一個頻道。所有的goroutines使用這個相同的頻道。

這會讓你像互斥體一樣使用這個通道。與

<-doingFileModicationJobs 

,然後替換你的僞代碼,

critical section{ 

更換匹配的結束與你的關鍵部分僞代碼的梅開二度,

doingFileModications <- false 

它很好地讀取方式相比更具描述像「互斥體」或「關鍵部分」這樣的一般術語。

這個連載你的文件的修改工作,並確保只有一次一個夠程可以做他們。我認爲這是一個關鍵部分的共同理念,但如果你真的需要其它夠程停下來,即使他們只是在做郵件發送任務,好,這是一個不同的問題。