diff --git a/examples.txt b/examples.txt index 289ee58..6153867 100644 --- a/examples.txt +++ b/examples.txt @@ -23,7 +23,6 @@ Goroutines Channels Channel Buffering Channel Synchronization -Waiting For Goroutines To Finish Channel Directions Select Timeouts @@ -33,6 +32,7 @@ Range over Channels Timers Tickers Worker Pools +WaitGroup Rate Limiting Atomic Counters Mutexes diff --git a/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.go b/examples/waitgroup/waitgroup.go similarity index 70% rename from examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.go rename to examples/waitgroup/waitgroup.go index db49ad4..65c4212 100644 --- a/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.go +++ b/examples/waitgroup/waitgroup.go @@ -1,27 +1,22 @@ // To wait for multiple goroutines to finish, we can -// use a sync.WaitGroup. +// use a *wait group*. package main import ( "fmt" - "math/rand" "sync" "time" ) // This is the function we'll run in every goroutine. -// wg is the WaitGroup it uses to notify that it's done. // Note that a WaitGroup must be passed to functions by // pointer. func worker(id int, wg *sync.WaitGroup) { fmt.Printf("Worker %d starting\n", id) - // Sleep for a random duration between 500-700 ms - // to simulate work. See the [random numbers](random-numbers) - // example for more details on *rand*. - msToSleep := time.Duration(500 + rand.Intn(200)) - time.Sleep(msToSleep * time.Millisecond) + // Sleep to simulate an expensive task. + time.Sleep(time.Second) fmt.Printf("Worker %d done\n", id) // Notify the WaitGroup that we're done. diff --git a/examples/waitgroup/waitgroup.hash b/examples/waitgroup/waitgroup.hash new file mode 100644 index 0000000..1df8a2f --- /dev/null +++ b/examples/waitgroup/waitgroup.hash @@ -0,0 +1,2 @@ +ffc6520e73ebfa2b8c470e3ef00fee55388234e0 +8cD2V9CgI0J diff --git a/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.sh b/examples/waitgroup/waitgroup.sh similarity index 85% rename from examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.sh rename to examples/waitgroup/waitgroup.sh index f68210c..13293bc 100644 --- a/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.sh +++ b/examples/waitgroup/waitgroup.sh @@ -1,4 +1,4 @@ -$ go run waiting-for-goroutines-to-finish.go +$ go run waitgroup.go Worker 5 starting Worker 3 starting Worker 4 starting diff --git a/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.hash b/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.hash deleted file mode 100644 index 00b9360..0000000 --- a/examples/waiting-for-goroutines-to-finish/waiting-for-goroutines-to-finish.hash +++ /dev/null @@ -1,2 +0,0 @@ -f068072d11ed9469174c18f5b7a6a7d9d8d3dafb -koKzXfbq8kg diff --git a/examples/worker-pools/worker-pools.go b/examples/worker-pools/worker-pools.go index 1114a22..443957e 100644 --- a/examples/worker-pools/worker-pools.go +++ b/examples/worker-pools/worker-pools.go @@ -12,37 +12,40 @@ import "time" // results on `results`. We'll sleep a second per job to // simulate an expensive task. func worker(id int, jobs <-chan int, results chan<- int) { - for j := range jobs { - fmt.Println("worker", id, "started job", j) - time.Sleep(time.Second) - fmt.Println("worker", id, "finished job", j) - results <- j * 2 - } + for j := range jobs { + fmt.Println("worker", id, "started job", j) + time.Sleep(time.Second) + fmt.Println("worker", id, "finished job", j) + results <- j * 2 + } } func main() { - // In order to use our pool of workers we need to send - // them work and collect their results. We make 2 - // channels for this. - jobs := make(chan int, 100) - results := make(chan int, 100) + // In order to use our pool of workers we need to send + // them work and collect their results. We make 2 + // channels for this. + jobs := make(chan int, 100) + results := make(chan int, 100) - // This starts up 3 workers, initially blocked - // because there are no jobs yet. - for w := 1; w <= 3; w++ { - go worker(w, jobs, results) - } + // This starts up 3 workers, initially blocked + // because there are no jobs yet. + for w := 1; w <= 3; w++ { + go worker(w, jobs, results) + } - // Here we send 5 `jobs` and then `close` that - // channel to indicate that's all the work we have. - for j := 1; j <= 5; j++ { - jobs <- j - } - close(jobs) + // Here we send 5 `jobs` and then `close` that + // channel to indicate that's all the work we have. + for j := 1; j <= 5; j++ { + jobs <- j + } + close(jobs) - // Finally we collect all the results of the work. - for a := 1; a <= 5; a++ { - <-results - } + // Finally we collect all the results of the work. + // This also ensures that the worker goroutines have + // finished. An alternative way to wait for multiple + // goroutines is to use a [WaitGroup](waitgroup). + for a := 1; a <= 5; a++ { + <-results + } } diff --git a/examples/worker-pools/worker-pools.hash b/examples/worker-pools/worker-pools.hash index 013b2de..ee8c3c7 100644 --- a/examples/worker-pools/worker-pools.hash +++ b/examples/worker-pools/worker-pools.hash @@ -1,2 +1,2 @@ -1f9acf1e50be05cad73e6b085ed3294892c67d42 -RTRcHA05vV +bfd2824b3840ff67fa9a0218c7be66647b4bf3d9 +IQestAFcxLh diff --git a/public/channel-synchronization b/public/channel-synchronization index 9c26e54..e79fe04 100644 --- a/public/channel-synchronization +++ b/public/channel-synchronization @@ -171,7 +171,7 @@ started.

- Next example: Waiting For Goroutines To Finish. + Next example: Channel Directions.

  • Channel Synchronization
  • -
  • Waiting For Goroutines To Finish
  • -
  • Channel Directions
  • Select
  • @@ -105,6 +103,8 @@
  • Worker Pools
  • +
  • WaitGroup
  • +
  • Rate Limiting
  • Atomic Counters
  • diff --git a/public/worker-pools b/public/worker-pools index baeb60a..8ff2427 100644 --- a/public/worker-pools +++ b/public/worker-pools @@ -40,7 +40,7 @@ a worker pool using goroutines and channels.

    - +
    package main
     
    @@ -147,7 +147,11 @@ channel to indicate that’s all the work we have.

    -

    Finally we collect all the results of the work.

    +

    Finally we collect all the results of the work. +This also ensures that the worker goroutines have +finished. An alternative way to wait for multiple +goroutines that’s useful in many scenarios is +to use a WaitGroup.

    @@ -207,7 +211,7 @@ there are 3 workers operating concurrently.

    - Next example: Rate Limiting. + Next example: WaitGroup.