千家信息网

Go 语言基础中goroutine和共享内存线程安全是怎样的

发表于:2024-11-20 作者:千家信息网编辑
千家信息网最后更新 2024年11月20日,Go 语言基础中goroutine和共享内存线程安全是怎样的,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。协程(goro
千家信息网最后更新 2024年11月20日Go 语言基础中goroutine和共享内存线程安全是怎样的

Go 语言基础中goroutine和共享内存线程安全是怎样的,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

协程(goroutine)是更轻量级的线程

比Java中的线程效率更高

协程语法
go func() {   //...}()

一旦主goroutine中的代码执行完毕,当前的Go程序就会结束运行,无论其他的 goroutine是否已经在运行了。

让主goroutine等待其它 goroutine:
for i := 0; i < 10; i++ {        go func() {                fmt.Println(i)        }()}time.Sleep(time.Millisecond * 1000)//goroutine 完成的时间很可能小于设置的等待时间,那么这就会造成多余的等待时间
怎么才能让goroutine执行完后立刻执行下一个goroutine呢?

go语言提供的WaitGroup可以实现这样的功能.

代码改造:

var wg sync.WaitGroupfor 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.WaitGroupfor 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也支持加锁保证线程的安全:

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)}


看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注行业资讯频道,感谢您对的支持。

0