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 goroutineを玉入れ競争に例えて理解しようとする

Posted at

玉入れ

田中君:1投あたり2秒
鈴木君:1投あたり1秒

ルール

  • 先に10球投げた方の勝ち → ゲーム終了
  • 玉入れ先は別々

ポイント

  • waitするスレッドを1として、1つでも並列スレッドが完了した場合、プログラムを終了させる。

package main

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

type Tomodachi struct {
	name           string
	per_throw_time int
	greeting       string
}

var greeting = "よろしくお願いします"

var tanaka = Tomodachi{
	name:           "tanaka",
	per_throw_time: 2,
	greeting:       greeting,
}

var suzuki = Tomodachi{
	name:           "suzuki",
	per_throw_time: 1,
	greeting:       greeting,
}

var wg = sync.WaitGroup{}

func main() {

	fmt.Printf("%vです。%v。\n", tanaka.name, greeting)
	fmt.Printf("%vです。%v。\n", suzuki.name, greeting)

	start_time := time.Now()
	// 待つスレッドの数
	wg.Add(1)
	go tamaire(tanaka.name, tanaka.per_throw_time)
	go tamaire(suzuki.name, suzuki.per_throw_time)

	fmt.Println("start")
	// スレッドから終わりの連絡を待つ。
	wg.Wait()
	// end_time := time.Now()

	elapsed_time := time.Since(start_time)

	fmt.Printf("経過時間 : %v\n", elapsed_time)
}

func tamaire(name string, per_throw_time int) {
	for i := 1; i < 100; i++ {
		time.Sleep(time.Duration(per_throw_time) * time.Second)
		if i == 10 {
			fmt.Printf("%v\n", time.Now())
			fmt.Printf("%v君%v投目\n", name, i)
			break
		}
		i := strconv.Itoa(i)
		fmt.Printf("%v\n", time.Now())
		fmt.Printf("%v君%v投目\n", name, i)

	}
	fmt.Printf("%v君の勝利!\n", name)
	// メインスレッドに「僕は終わったよ」と伝える。
	wg.Done()
}


実行結果


tanakaです。よろしくお願いします。
suzukiです。よろしくお願いします。
start
suzuki君1投目
tanaka君1投目
suzuki君2投目
suzuki君3投目
tanaka君2投目
suzuki君4投目
suzuki君5投目
tanaka君3投目
suzuki君6投目
suzuki君7投目
tanaka君4投目
suzuki君8投目
suzuki君9投目
tanaka君5投目
suzuki君10投目
suzuki君の勝利!
経過時間 : 10.0233975s


次に2人とも終了するまでゲームが終わらない場合

ポイント

  • waitするスレッドを2とする。

package main

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

type Tomodachi struct {
	name           string
	per_throw_time int
	greeting       string
}

var greeting = "よろしくお願いします"

var tanaka = Tomodachi{
	name:           "tanaka",
	per_throw_time: 2,
	greeting:       greeting,
}

var suzuki = Tomodachi{
	name:           "suzuki",
	per_throw_time: 1,
	greeting:       greeting,
}

var wg = sync.WaitGroup{}

func main() {

	fmt.Printf("%vです。%v。\n", tanaka.name, greeting)
	fmt.Printf("%vです。%v。\n", suzuki.name, greeting)

	start_time := time.Now()
	// 待つスレッドの数
	wg.Add(2)
	go tamaire(tanaka.name, tanaka.per_throw_time)
	go tamaire(suzuki.name, suzuki.per_throw_time)

	fmt.Println("start")
	// スレッドから終わりの連絡を待つ。
	wg.Wait()
	wg.Wait()
	// end_time := time.Now()

	elapsed_time := time.Since(start_time)

	fmt.Printf("経過時間 : %v\n", elapsed_time)
}

func tamaire(name string, per_throw_time int) {
	for i := 1; i < 100; i++ {
		time.Sleep(time.Duration(per_throw_time) * time.Second)
		if i == 10 {
			fmt.Printf("%v\n", time.Now())
			fmt.Printf("%v君%v投目\n", name, i)
			break
		}
		i := strconv.Itoa(i)
		fmt.Printf("%v\n", time.Now())
		fmt.Printf("%v君%v投目\n", name, i)

	}
	// fmt.Printf("%v君の勝利!\n", name)
	fmt.Printf("%v君終了!\n", name)
	// メインスレッドに「僕は終わったよ」と伝える。
	wg.Done()
}


終了結果


tanakaです。よろしくお願いします。
suzukiです。よろしくお願いします。
start
2021-12-26 00:29:47.9075919 +0900 JST m=+1.003917701
suzuki君1投目
2021-12-26 00:29:48.9075828 +0900 JST m=+2.003908601
tanaka君1投目
2021-12-26 00:29:48.9463528 +0900 JST m=+2.042678601
suzuki君2投目
2021-12-26 00:29:49.94648 +0900 JST m=+3.042805801
suzuki君3投目
2021-12-26 00:29:50.9080411 +0900 JST m=+4.004366901
tanaka君2投目
2021-12-26 00:29:50.9578967 +0900 JST m=+4.054222501
suzuki君4投目
2021-12-26 00:29:51.9588457 +0900 JST m=+5.055171501
suzuki君5投目
2021-12-26 00:29:52.9085968 +0900 JST m=+6.004922601
tanaka君3投目
2021-12-26 00:29:52.9710026 +0900 JST m=+6.067328401
suzuki君6投目
2021-12-26 00:29:53.9724243 +0900 JST m=+7.068750101
suzuki君7投目
2021-12-26 00:29:54.9105403 +0900 JST m=+8.006866101
tanaka君4投目
2021-12-26 00:29:54.973832 +0900 JST m=+8.070157801
suzuki君8投目
2021-12-26 00:29:55.9756013 +0900 JST m=+9.071927101
suzuki君9投目
2021-12-26 00:29:56.9254739 +0900 JST m=+10.021799701
tanaka君5投目
2021-12-26 00:29:56.9756559 +0900 JST m=+10.071981701
suzuki君10投目
suzuki君終了!
2021-12-26 00:29:58.9264477 +0900 JST m=+12.022773501
tanaka君6投目
2021-12-26 00:30:00.9271847 +0900 JST m=+14.023510501
tanaka君7投目
2021-12-26 00:30:02.9272481 +0900 JST m=+16.023573901
tanaka君8投目
2021-12-26 00:30:04.9276392 +0900 JST m=+18.023965001
tanaka君9投目
2021-12-26 00:30:06.9292777 +0900 JST m=+20.025603501
tanaka君10投目
tanaka君終了!
経過時間 : 20.0232072s

最後に念のため、wg.wait(0)した時の結果を確認


package main

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

type Tomodachi struct {
	name           string
	per_throw_time int
	greeting       string
}

var greeting = "よろしくお願いします"

var tanaka = Tomodachi{
	name:           "tanaka",
	per_throw_time: 2,
	greeting:       greeting,
}

var suzuki = Tomodachi{
	name:           "suzuki",
	per_throw_time: 1,
	greeting:       greeting,
}

var wg = sync.WaitGroup{}

func main() {

	fmt.Printf("%vです。%v。\n", tanaka.name, greeting)
	fmt.Printf("%vです。%v。\n", suzuki.name, greeting)

	start_time := time.Now()
	// 待つスレッドの数
	wg.Add(0)
	go tamaire(tanaka.name, tanaka.per_throw_time)
	go tamaire(suzuki.name, suzuki.per_throw_time)

	fmt.Println("start")
	// スレッドから終わりの連絡を待つ。
	wg.Wait()
	wg.Wait()
	// end_time := time.Now()

	elapsed_time := time.Since(start_time)

	fmt.Printf("経過時間 : %v\n", elapsed_time)
}

func tamaire(name string, per_throw_time int) {
	for i := 1; i < 100; i++ {
		time.Sleep(time.Duration(per_throw_time) * time.Second)
		if i == 10 {
			fmt.Printf("%v\n", time.Now())
			fmt.Printf("%v君%v投目\n", name, i)
			break
		}
		i := strconv.Itoa(i)
		fmt.Printf("%v\n", time.Now())
		fmt.Printf("%v君%v投目\n", name, i)

	}
	// fmt.Printf("%v君の勝利!\n", name)
	fmt.Printf("%v君終了!\n", name)
	// メインスレッドに「僕は終わったよ」と伝える。
	wg.Done()
}


実行結果


tanakaです。よろしくお願いします。
suzukiです。よろしくお願いします。
start
経過時間 : 773.9µs


goroutineが始まる前にメインスレッドが終了。

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?