0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

[Go] 並行処理を30分で理解?

Posted at

Goroutinesってなに?

educativeには、以下のように書いてあります。

ゴルーチンとは、Goプログラミング言語における軽量の実行スレッドであり、プログラムの他の部分と同時に実行される関数です。
ゴルーチンは、従来のスレッドと比較すると、ゴルーチンを作成するオーバーヘッドが非常に小さいため、驚くほど安価です。そのため、Goでは並行プログラミングに広く使われています。
関数をgoroutineとして呼び出すには、goキーワードを使用します。

なるほど、わからん。まぁとりあえず、 同時に実行される ということですね。

コードのテンプレート

2つの関数 heyko1()heyko2() が同時に実行される(並行処理される)ための関数 main() を作成します。

goroutinesを呼び出すときには、基本的には呼び出すところで関数の前にgoをつけることで並行処理として利用できます。これだけで並行処理にできるというところがgoのいいところなんです。

まず、基本的に以下のような形で書きました。

func main() {
    // 普通の処理(同期処理)
    normalFunc()

    // 並行処理(goroutinesとして呼び出す)
    go parallelFunc()
}

goをつけるかつけないかだけです。

次に、関数を2つ作り、並行処理を簡単に実装してみます。

template
package main

import (
    "fmt"
    "sync"
)

// heyko1 はgoroutineで実行する最初の関数です。
func heyko1(wg *sync.WaitGroup) {
    defer wg.Done() // 関数終了時にWaitGroupのカウントをデクリメント

    // ここにheyko1の処理を書きます
    fmt.Println("heyko1 の実行中です")
}

// heyko2 はgoroutineで実行する2番目の関数です。
func heyko2(wg *sync.WaitGroup) {
    defer wg.Done() // 関数終了時にWaitGroupのカウントをデクリメント

    // ここにfunction2の処理を書きます
    fmt.Println("heyko2 の実行中です")
}

func main() {
    var wg sync.WaitGroup // WaitGroupの初期化

    wg.Add(2) // WaitGroupのカウントを2つのgoroutineの数だけインクリメント

    go heyko1(&wg) // heyko1をgoroutineとして実行
    go heyko2(&wg) // heyko2をgoroutineとして実行

    wg.Wait() // すべてのgoroutineの終了を待機
    fmt.Println("全て終了")
}


基本的にこのような形になります。これらを実際に時間の処理を入れてみましょう。

時間を入れた処理
package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {

	fmt.Println("はじまり〜")
	var wg sync.WaitGroup

	// WaitGroupのカウンタを2つ増やす
	wg.Add(2)

	// process1をgoroutineとして実行
	go func() {
		heyko1() 
		defer wg.Done() // 処理が完了したらWaitGroupのカウンタを減らす
	}()

	// process2をgoroutineとして実行
	go func() {
		heyko2()
		defer wg.Done() // 処理が完了したらWaitGroupのカウンタを減らす
	}()

	// すべてのgoroutineが終了するのを待つ
	wg.Wait()

	fmt.Println("おわり〜")
}

func heyko1() {
	start := time.Now()
	time.Sleep(10 * time.Second)
	end := time.Now()
	fmt.Println("heyko1: ", (end.Sub(start)).Seconds())
	fmt.Println("heyko1: ", start.Format("2006-01-02T15:04:05Z07:00"), "~~", end.Format("2006-01-02T15:04:05Z07:00"))
}

func heyko2() {
	start := time.Now()
	end := time.Now()
	fmt.Println("heyko2: ", (end.Sub(start)).Seconds())
	fmt.Println("heyko2: ", start.Format("2006-01-02T15:04:05Z07:00"), "~~", end.Format("2006-01-02T15:04:05Z07:00"))
}

↓ 実行結果

はじまり〜
heyko2:  1.27e-07
heyko2:  2024-02-23T16:13:07+09:00 ~~ 2024-02-23T16:13:07+09:00
heyko1:  10.000868864
heyko1:  2024-02-23T16:13:07+09:00 ~~ 2024-02-23T16:13:17+09:00
おわり〜

なぜ時間で書いたかというと、heyko1とheyko2の始まるタイミングと終わるタイミングが同じであり、処理時間が違うため、終了時間が異なることを確認するためです。

実際に

heyko2:  2024-02-23T16:13:07+09:00 ~~ 2024-02-23T16:13:07+09:00
heyko1:  2024-02-23T16:13:07+09:00 ~~ 2024-02-23T16:13:17+09:00

となっているため、始まりは一緒の2024-02-23T16:13:07+09:00 です。
そのあとは、10秒の差があって、終わっています。

実体験で感じれましたね!

以上!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?