协程(goroutine)是更轻量级的线程安全
比Java中的线程效率更高线程
go func() { //... }()
一旦主goroutine中的代码执行完毕,当前的Go程序就会结束运行,不管其余的 goroutine是否已经在运行了。code
for i := 0; i < 10; i++ { go func() { fmt.Println(i) }() } time.Sleep(time.Millisecond * 1000) //goroutine 完成的时间极可能小于设置的等待时间,那么这就会形成多余的等待时间
go语言提供的WaitGroup能够实现这样的功能.协程
代码改造:对象
var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1)//每启动一个协程增长一个等待 go func() { fmt.Println(i) wg.Done()//告诉协成等待的事务已经完成 }() } /* 这样咱们就不用设置等待时间了,可是执行输出的内容是这样的: 3 7 4 8 8 8 9 10 10 10, 很显然这种方式不能保证goroutine拿到惟一整数 */
代码改造:事务
var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1)//每启动一个协程增长一个等待 go func(j int) {//把j只是个形参能够任意命名 fmt.Println(j) wg.Done()//告诉协成等待的事务已经完成 }(i)//把实参i传递给形参j } //执行结果:0 2 1 6 3 4 5 8 7 9
咱们把i值传递给j,i的变化不会影响j的值,因此输出的结果是惟一的内存
func TestCounter(t *testing.T) { counter := 0 for i := 0; i < 5000; i++ { go func() { counter++ }() } time.Sleep(1 * time.Second) t.Logf("counter = %d", counter) } //执行结果: 4760 出现了线程安全的问题
和大多数语言同样go也支持加锁保证线程的安全:it
func TestCounterWaitGroup(t *testing.T) { var mut sync.Mutex//建立锁对象 var wg sync.WaitGroup 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) }
**** 码字不易若是对你有帮助请给个关注****class
**** 爱技术爱生活 QQ群: 894109590****test