2

在我的代码中有三个并发例程。我尝试简要概述我的代码,

Routine 1 {
do something

*Send int to Routine 2
Send int to Routine 3
Print Something
Print Something*

do something
}

Routine 2 {
do something

*Send int to Routine 1
Send int to Routine 3
Print Something
Print Something*

do something
}

Routine 3 {
do something

*Send int to Routine 1
Send int to Routine 2
Print Something
Print Something*

do something
}

main {
routine1
routine2
routine3
}

我想要这样,当两个之间的代码做某事(两个星号之间的代码)正在执行时,控制流不能转到其他 goroutines。例如,当例程 1 正在执行两颗星之间的事件(发送和打印事件)时,例程 2 和 3 必须被阻塞(意味着执行流程不会从例程 1 传递到例程 2 或 3)。完成最后一个打印事件后,执行流程可能会转到例程 2 或 3。任何人都可以通过指定来帮助我,我该如何实现?是否可以通过WaitGroup实现上述规范?任何人都可以通过给出一个简单的例子来告诉我如何使用 WaitGroup 来实现上述指定的例子。谢谢。

注意:我给出了两个发送和两个打印选项,实际上有很多发送和打印。

4

4 回答 4

3

如果我理解正确,您想要的是防止同时执行每个功能的某些部分和其他功能。以下代码执行此操作:fmt.Println在其他例程运行时不会发生行。以下是发生的情况:当执行到达打印部分时,它会一直等到其他例程结束,如果它们正在运行,并且当此打印行正在执行时,其他例程不会启动并等待。我希望这就是你要找的。如果我对此有误,请纠正我。

package main

import (
    "fmt"
    "rand"
    "sync"
)

var (
    mutex1, mutex2, mutex3 sync.Mutex
    wg sync.WaitGroup
)

func Routine1() {
    mutex1.Lock()
    // do something
    for i := 0; i < 200; i++ {
        mutex2.Lock()
        mutex3.Lock()
        fmt.Println("value of z")
        mutex2.Unlock()
        mutex3.Unlock()
    }
    // do something
    mutex1.Unlock()
    wg.Done()
}

func Routine2() {
    mutex2.Lock()
    // do something
    for i := 0; i < 200; i++ {
        mutex1.Lock()
        mutex3.Lock()
        fmt.Println("value of z")
        mutex1.Unlock()
        mutex3.Unlock()
    }
    // do something
    mutex2.Unlock()
    wg.Done()
}

func Routine3() {
    mutex3.Lock()
    // do something
    for i := 0; i < 200; i++ {
        mutex1.Lock()
        mutex2.Lock()
        fmt.Println("value of z")
        mutex1.Unlock()
        mutex2.Unlock()
    }
    // do something
    mutex3.Unlock()
    wg.Done()
}

func main() {
    wg.Add(3)
    go Routine1()
    go Routine2()
    Routine3()
    wg.Wait()
}

更新:让我在这里解释这三个互斥锁:互斥锁,如文档所述:“互斥锁”。这意味着当您调用互斥锁时Lock,如果其他人锁定了同一个互斥锁,您的代码就会在那里等待。在您调用Unlock该被阻止的代码后,将立即恢复。

在这里,我通过在函数开头锁定互斥锁并在结尾解锁互斥锁,将每个函数放入自己的互斥锁中。通过这种简单的机制,您可以避免在运行这些函数的同时运行您想要的任何代码部分。例如,您希望在任何地方都有一个在运行时不应该运行的代码Routine1,只需mutex1在该代码的开头锁定并在末尾解锁即可。这就是我在 和 的适当行中所做Routine2Routine3。希望能澄清事情。

于 2011-11-30T00:50:26.987 回答
2

你可以使用sync.Mutex. 例如,介于im.Lock()和之间的所有内容都im.Unlock()将排除另一个 goroutine。

package main

import (
"fmt"
"sync"
)

func f1(wg *sync.WaitGroup, im *sync.Mutex, i *int) {
  for {
    im.Lock()
    (*i)++
    fmt.Printf("Go1: %d\n", *i)
    done := *i >= 10
    im.Unlock()
    if done {
      break
    }
  }
  wg.Done()
}

func f2(wg *sync.WaitGroup, im *sync.Mutex, i *int) {
  for {
    im.Lock()
    (*i)++
    fmt.Printf("Go2: %d\n", *i)
    done := *i >= 10
    im.Unlock()
    if done {
      break
    }
  }
  wg.Done()
}

func main() {
    var wg sync.WaitGroup

    var im sync.Mutex
    var i int

    wg.Add(2)
    go f1(&wg, &im, &i)
    go f2(&wg, &im, &i)
    wg.Wait()   

}
于 2011-11-29T21:06:29.060 回答
0

另一种方法是拥有一个控制通道,在任何时候只允许执行一个 goroutine,每个例程在完成原子操作后发送回“控制锁”:

package main
import "fmt"
import "time"

func routine(id int, control chan struct{}){
    for {
        // Get the control
        <-control
        fmt.Printf("routine %d got control\n", id)
        fmt.Printf("A lot of things happen here...")
        time.Sleep(1)
        fmt.Printf("... but only in routine %d !\n", id)
        fmt.Printf("routine %d gives back control\n", id)
        // Sending back the control to whichever other routine catches it
        control<-struct{}{}
    }
}

func main() {
    // Control channel is blocking
    control := make(chan struct{})

    // Start all routines
    go routine(0, control)
    go routine(1, control)
    go routine(2, control)

    // Sending control to whichever catches it first
    control<-struct{}{}
    // Let routines play for some time...
    time.Sleep(10)
    // Getting control back and terminating
    <-control
    close(control)
    fmt.Println("Finished !")
}

这打印:

routine 0 got control
A lot of things happen here...... but only in routine 0 !
routine 0 gives back control
routine 1 got control
A lot of things happen here...... but only in routine 1 !
routine 1 gives back control
routine 2 got control
A lot of things happen here...... but only in routine 2 !
routine 2 gives back control
routine 0 got control
A lot of things happen here...... but only in routine 0 !
routine 0 gives back control
routine 1 got control
A lot of things happen here...... but only in routine 1 !
routine 1 gives back control
routine 2 got control
A lot of things happen here...... but only in routine 2 !
routine 2 gives back control
routine 0 got control
A lot of things happen here...... but only in routine 0 !
routine 0 gives back control
routine 1 got control
A lot of things happen here...... but only in routine 1 !
routine 1 gives back control
routine 2 got control
A lot of things happen here...... but only in routine 2 !
routine 2 gives back control
routine 0 got control
A lot of things happen here...... but only in routine 0 !
routine 0 gives back control
routine 1 got control
A lot of things happen here...... but only in routine 1 !
routine 1 gives back control
routine 2 got control
A lot of things happen here...... but only in routine 2 !
routine 2 gives back control
Finished !
于 2013-08-14T09:06:24.613 回答
-2

您要求一个明确停止其他例程的库函数?明确指出,这在 Go 和大多数其他语言中都是不可能的。对于您的情况,同步,互斥锁情况是不可能的。

于 2011-11-29T18:52:25.327 回答