Skip to content

Instantly share code, notes, and snippets.

@tkm-kj
Last active September 9, 2020 07:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tkm-kj/7888f749c156702e9908e304f6ba8251 to your computer and use it in GitHub Desktop.
Save tkm-kj/7888f749c156702e9908e304f6ba8251 to your computer and use it in GitHub Desktop.
golangで並行処理のお勉強
package main
import (
"fmt"
"math/rand"
"sync"
"time"
"github.com/pkg/errors"
)
func func1(wg *sync.WaitGroup) {
defer wg.Done()
time.Sleep(time.Second * 15)
rand.Seed(time.Now().UnixNano())
if rand.Intn(2) >= 1 {
fmt.Println("func1 error!")
return
}
fmt.Println("func1 finish")
}
func func2(wg *sync.WaitGroup) {
defer wg.Done()
time.Sleep(time.Second * 10)
rand.Seed(time.Now().UnixNano())
if rand.Intn(2) >= 1 {
fmt.Println("func2 error!")
return
}
fmt.Println("func2 finish")
}
// WaitGroupとchannelを組み合わせる方式
// 同時接続の数を絞ることが出来る
// 並行処理させたいが、外部の何かに依存している時に有効
func func3(wg *sync.WaitGroup) {
defer wg.Done()
limit := 10
// 構造体で埋める理由: ディスクリプタ(記述子)の大きさが小さいから(?)
// https://dave.cheney.net/2014/03/25/the-empty-struct
slots := make(chan struct{}, limit)
defer close(slots)
var wg2 sync.WaitGroup
cnt := 0
for {
cnt++
wg2.Add(1)
// channel の capacity の性質により、 capacity に空きが無い場合は送信側が処理待ち(ブロック)してくれる
slots <- struct{}{}
go func(c int) {
defer wg2.Done()
time.Sleep(time.Second * 1)
fmt.Println("index: ", c)
// channel に空きが生まれる
<-slots
}(cnt)
if cnt >= 30 {
break
}
}
// Wait は繰り返しの外側に書いてあげないと正しく動かないので注意
wg2.Wait()
rand.Seed(time.Now().UnixNano())
if rand.Intn(2) >= 1 {
fmt.Println("func3 error!")
return
}
fmt.Println("func3 finish")
}
// WaitGroupのみ
// ひたすら同時並行で投げまくりたい && 処理の終わりは確認したい時有効
func func4(wg *sync.WaitGroup) {
defer wg.Done()
var wg2 sync.WaitGroup
for i := 0; i < 60; i++ {
wg2.Add(1)
go func(index int) {
defer wg2.Done()
time.Sleep(time.Second * 1)
rand.Seed(time.Now().UnixNano())
fmt.Println("func4: ", index)
}(i)
}
wg2.Wait()
rand.Seed(time.Now().UnixNano())
if rand.Intn(2) >= 1 {
fmt.Println("func4 error!")
return
}
fmt.Println("func4 finish")
}
func func5(wg *sync.WaitGroup) {
defer wg.Done()
time.Sleep(time.Second * 5)
rand.Seed(time.Now().UnixNano())
if rand.Intn(2) >= 1 {
fmt.Println("func5 error!")
return
}
fmt.Println("func5 finish")
}
func main() {
fmt.Println("start!")
var wg sync.WaitGroup
wg.Add(6)
go func1(&wg)
go func2(&wg)
go func3(&wg)
go func4(&wg)
go func5(&wg)
go func() {
defer wg.Done()
time.Sleep(time.Second * 3)
fmt.Printf("%+v\n", errors.Wrap(errors.New("anonymous function error!"), ""))
}()
wg.Wait()
fmt.Println("finish!")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment