一、使用关键字go并发
package groutine_test import ( "fmt" "testing" "time" ) func TestGroutine(t *testing.T) { for i := 0; i < 10; i++ { //启动协程 go func(i int) { fmt.Println(i) }(i) } time.Sleep(time.Millisecond * 50) }
=== RUN TestGroutine 9 5 6 7 8 1 0 2 3 4 --- PASS: TestGroutine (0.05s) PASS
二、并发锁
package share_mem import ( "sync" "testing" "time" ) //协程不安全 func TestCounter(t *testing.T) { counter := 0 for i := 0; i < 5000; i++ { //并发计数 go func() { counter++ }() } time.Sleep(time.Second * 1) t.Logf("counter=%d", counter) } //协程安全 func TestCounterThreadSafe(t *testing.T) { //获取锁 var mut sync.Mutex counter := 0 for i := 0; i < 5000; i++ { //并发计数 go func() { //延迟解锁 defer func() { mut.Unlock() }() //加锁 mut.Lock() counter++ }() } time.Sleep(time.Second * 1) t.Logf("counter=%d", counter) } //WaitGroup 所有组完成后,继续执行 func TestCounterWaitGroup(t *testing.T) { //获取锁 var wg sync.WaitGroup var mut sync.Mutex counter := 0 for i := 0; i < 5000; i++ { wg.Add(1) //并发计数 go func() { //延迟解锁 defer func() { mut.Unlock() }() //加锁 mut.Lock() counter++ wg.Done() }() } wg.Wait() t.Logf("counter=%d", counter) }
三、异步执行
package csp import ( "fmt" "testing" "time" ) //串行 func service() string { time.Sleep(time.Millisecond * 50) return "Done" } //串行 func otherTask() { fmt.Println("working on somthing else") time.Sleep(time.Millisecond * 100) fmt.Println("Task is done.") } func TestService(t *testing.T) { fmt.Println(service()) otherTask() } //异步 chan在go中是一个通道有可读可写的chan,也存在只读只写的chan 异步返回 func AsyncService() chan string { //创建接受通道 retCh := make(chan string, 1) go func() { ret := service() fmt.Println("returned result.") //chan放数据 retCh <- ret fmt.Println("service exited.") }() return retCh } func TestAsynService(t *testing.T) { retCh := AsyncService() otherTask() //chan取数据 fmt.Println(<-retCh) //time.Sleep(time.Second * 1) }
异步执行后,快乐0.06s