You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

85 lines
2.0 KiB

  1. // Copyright 2017 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package semaphore_test
  5. import (
  6. "context"
  7. "fmt"
  8. "log"
  9. "runtime"
  10. "golang.org/x/sync/semaphore"
  11. )
  12. // Example_workerPool demonstrates how to use a semaphore to limit the number of
  13. // goroutines working on parallel tasks.
  14. //
  15. // This use of a semaphore mimics a typical “worker pool” pattern, but without
  16. // the need to explicitly shut down idle workers when the work is done.
  17. func Example_workerPool() {
  18. ctx := context.TODO()
  19. var (
  20. maxWorkers = runtime.GOMAXPROCS(0)
  21. sem = semaphore.NewWeighted(int64(maxWorkers))
  22. out = make([]int, 32)
  23. )
  24. // Compute the output using up to maxWorkers goroutines at a time.
  25. for i := range out {
  26. // When maxWorkers goroutines are in flight, Acquire blocks until one of the
  27. // workers finishes.
  28. if err := sem.Acquire(ctx, 1); err != nil {
  29. log.Printf("Failed to acquire semaphore: %v", err)
  30. break
  31. }
  32. go func(i int) {
  33. defer sem.Release(1)
  34. out[i] = collatzSteps(i + 1)
  35. }(i)
  36. }
  37. // Acquire all of the tokens to wait for any remaining workers to finish.
  38. //
  39. // If you are already waiting for the workers by some other means (such as an
  40. // errgroup.Group), you can omit this final Acquire call.
  41. if err := sem.Acquire(ctx, int64(maxWorkers)); err != nil {
  42. log.Printf("Failed to acquire semaphore: %v", err)
  43. }
  44. fmt.Println(out)
  45. // Output:
  46. // [0 1 7 2 5 8 16 3 19 6 14 9 9 17 17 4 12 20 20 7 7 15 15 10 23 10 111 18 18 18 106 5]
  47. }
  48. // collatzSteps computes the number of steps to reach 1 under the Collatz
  49. // conjecture. (See https://en.wikipedia.org/wiki/Collatz_conjecture.)
  50. func collatzSteps(n int) (steps int) {
  51. if n <= 0 {
  52. panic("nonpositive input")
  53. }
  54. for ; n > 1; steps++ {
  55. if steps < 0 {
  56. panic("too many steps")
  57. }
  58. if n%2 == 0 {
  59. n /= 2
  60. continue
  61. }
  62. const maxInt = int(^uint(0) >> 1)
  63. if n > (maxInt-1)/3 {
  64. panic("overflow")
  65. }
  66. n = 3*n + 1
  67. }
  68. return steps
  69. }