1. Using sync.WaitGroup
A sync.WaitGroup is a way to coordinate multiple goroutines by reporting completion. Since there’s nobody to report completion, it never returns. Wait blocks until the WaitGroup counter is zero.app
package main import "sync" func main() { var wg sync.WaitGroup wg.Add(1) wg.Wait() }
2. Empty select
This function tries to select the first case that returns, so it will happily wait forever for nothing to return.less
package main func main() { select{} }
3. Double Locking
If the lock is already in use, the calling goroutine blocks until the mutex is available.ide
package main import "sync" func main() { var m sync.Mutex m.Lock() m.Lock() }
The same trick works with a sync.RWMutex that has been RLock()’d.oop
4. Empty Channel
Empty channels will block until there is something to receive.ui
package main func main() { c := make(chan struct{}) <-c }
This also works with a nil channel not made with make()this
5. Infinite loop
The easiest way which will use 100% of CPU.code
package main func main() { for {} }
6. goto
package main func main() { start: goto start }
7. defer
func main() { defer main() }
8. Busy Blocking
This method technically doesn’t block, it just constantly defers to other work if it’s available.blog
package main import "runtime" func main() { for { runtime.Gosched() } }
9. The Decomposed Loop
Same as before, not technically blocking but looping and deferring to other work.ip
package main import "runtime" func main() { foo: runtime.Gosched() goto foo }
10. Shaking my Own Hand
This is a bit like shaking your own hand. This function will continually send a useless message to itself until the end of time. The channel send operations are opportunities for the runtime to schedule other goroutines, so this method would not monopolize a single processor.get
package main func main() { c := make(chan struct{}, 1) for { select { case <-c: case c <- struct{}{}: } } }
11. Sleeping for a Looooong Time
Sleeping to the maximum time allowed takes quite a long time, roughly 292.4 years. Likely, your code won’t run that long, so I’d consider this equivalent to select{}.
package main import ( "math" "time" ) func main() { <-time.After(time.Duration(math.MaxInt64)) }
12. Signal
package main import ( "os" "os/signal" "syscall" ) func main() { // exit program on ps kill and Ctrl+C... exitc := make(chan os.Signal, 1) signal.Notify(exitc, os.Interrupt, os.Kill, syscall.SIGTERM) // some code or goroutines // ... <-exitc // some cleanup or signal logging and printing }
总结
以上 1-4 之前都好使,如今好像不行了,会报错。
fatal error: all goroutines are asleep - deadlock! ...