2014-08-03 4 views
5

Учитывая следующий код:Параллельная обработка в golang

package main 

import (
    "fmt" 
    "math/rand" 
    "time" 
) 

func main() { 
    for i := 0; i < 3; i++ { 
     go f(i) 
    } 

    // prevent main from exiting immediately 
    var input string 
    fmt.Scanln(&input) 
} 

func f(n int) { 
    for i := 0; i < 10; i++ { 
     dowork(n, i) 
     amt := time.Duration(rand.Intn(250)) 
     time.Sleep(time.Millisecond * amt) 
    } 
} 

func dowork(goroutine, loopindex int) { 
    // simulate work 
    time.Sleep(time.Second * time.Duration(5)) 
    fmt.Printf("gr[%d]: i=%d\n", goroutine, loopindex) 
} 

Могу ли я считать, что функция «DoWork» будет выполняться параллельно?

Является ли это правильным способом достижения параллелизма или лучше использовать каналы и отдельных рабочих «доков» для каждого горутина?

+1

На всякий случай кто-то сочтет это интересным: [Эта статья] (http://www.golangpatterns.info/concurrency/parallel-for-loop) объясняет, как делать парал el для петель в Go. – rath

+0

@rath Большое спасибо - этот сайт окажется для меня фантастическим ресурсом! –

ответ

10

Ваш код будет работать одновременно, но не параллельно. Вы можете запустить его параллельно, установив GOMAXPROCS; см. статью http://www.goinggo.net/2014/01/concurrency-goroutines-and-gomaxprocs.html за хорошее резюме.

Непонятно, что именно вы пытаетесь выполнить здесь, но это выглядит как совершенно правильный способ достижения параллелизма для меня.

+0

Я следил за приведенным выше примером статьи. Я не получаю такой же результат. методы выполняются последовательно не параллельно. – Gnana

0

f() будет выполняться одновременно, но многие dowork() будут выполняться последовательно в пределах каждого f(). Ожидание на stdin также не является правильным способом обеспечить выполнение ваших подпрограмм. Вы должны развернуть канал, который каждый f() подталкивает true, когда заканчивается f(). В конце main() вы должны дождаться n номера true на канале. n - число f(), которое вы развернули.

+0

'sync.WaitGroup' лучше, чем канал для этого случая. – captncraig

3

Что касается GOMAXPROCS, вы можете найти это в документации выпуска Go 1.5 в:

По умолчанию Go программ работают с GOMAXPROCS, установленной на количество доступных ядер; в предыдущих версиях он по умолчанию 1.

Что касается предотвращения функции main от выхода сразу, вы можете использовать функцию WaitWaitGroup «s.

Я написал эту функцию полезности, чтобы помочь распараллеливаниям группы функций:

import "sync" 

// Parallelize parallelizes the function calls 
func Parallelize(functions ...func()) { 
    var waitGroup sync.WaitGroup 
    waitGroup.Add(len(functions)) 

    defer waitGroup.Wait() 

    for _, function := range functions { 
     go func(copy func()) { 
      defer waitGroup.Done() 
      copy() 
     }(function) 
    } 
} 

Так что в вашем случае, мы могли бы сделать это

func1 := func() { 
    f(0) 
} 

func2 = func() { 
    f(1) 
} 

func3 = func() { 
    f(2) 
} 

Parallelize(func1, func2, func3) 

Если вы хотите использовать функцию распараллеливания, вы можно найти здесь https://github.com/shomali11/util

Смежные вопросы