go中锁的作用范围

阅读: 评论:0

go中锁的作用范围

go中锁的作用范围

网上介绍sync.Mutex的文章已经很多了,这里也不深提。

具体就两种,一个互斥锁sync.Mutex;一个读写锁sync.RWMutex。

两种锁都有两个方法:Lock()和Unlock()。

互斥锁就是,其他线程不能读也不能写;

读写锁就是,其他线程可以读但是不能写。

 

但是由于网上的例子大多形式为:

var(

mtx sync.RWMutex

a int

)

或者为:

type A struct{

mtx sync.RWMutex

a int

}

导致go语言初学者的我以为锁是控制和该锁定义在一起的变量的。

然后写了几个小例子来了解go的锁的作用范围。

 

单个线程中加锁,主线程中修改值

看个简单的例子

package main
import (
"fmt"
"time"
"sync"
)func main(){var wg sync.WaitGroup//定义一个变量一个锁var (mtx1 sync.Mutexa int)wg.Add(1)go func(){mtx1.Lock()//加个锁a=114fmt.Println("[1]-->: ",a)//输出一下设定的a的值//睡眠5s后再输出一下a的值,因为在2s后a的值已经在主线程中被更改了time.Sleep(5 * time.Second)fmt.Println("[2]-->: ",a)mtx1.Unlock()//解锁wg.Done()}()//睡眠2s后更改一下a的值time.Sleep(2 * time.Second)a = 514wg.Wait()
}

输出为:

[root@vm10-0-0-63 gopath]# go  
[1]-->:  114
[2]-->:  514
 

疑问:“诶我不是加了锁了么,为什么a的值还会变?”

然后发现,噢,加了锁后不是说中间的内容不能变,锁也没那么智能会去分析你加锁后到底修改了哪些东西。

锁就只能保证,如果某个锁加锁了,那么别的地方再碰到这个锁就会阻塞,没碰到,那该干什么还干什么。

上面的例子在主线程中加锁后,变成如下代码:

package main
import (
"fmt"
"time"
"sync"
)func main(){var wg sync.WaitGroupvar (mtx1 sync.Mutexa int)a=114wg.Add(1)go func(){mtx1.Lock()//加个锁fmt.Println("[1]-->: ",a)//输出一下设定的a的值//睡眠5s后再输出一下a的值,因为在2s后a的值已经在主线程中被更改了time.Sleep(5 * time.Second)fmt.Println("[2]-->: ",a)mtx1.Unlock()//解锁wg.Done()}()//睡眠2s后更改一下a的值time.Sleep(2 * time.Second)mtx1.Lock()//加个锁a = 514mtx1.Unlock()//解锁fmt.Println("[3]-->: ",a)wg.Wait()
}

输出为:

[root@vm10-0-0-63 gopath]# go  
[1]-->:  114
[2]-->:  114
[3]-->:  514

 

这样就达成了想要达成的目的,主线程想要修改a的值,但是碰到了锁,就只能阻塞住。

所以虽然主线程是睡眠2s后想修改a为514,但实际上需要等待分线程睡眠5s,解锁后才能修改值,所以在分线程中的[2]仍然为114,最后输出的[3]才为514。

 

 

再举个例子:

单个线程中加锁,主线程加不同的锁并修改值

依然是上面的例子,稍微修改一下:

package main
import (
"fmt"
"time"
"sync"
)func main(){var wg sync.WaitGroupvar (mtx1 sync.Mutexmtx2 sync.Mutexa int)a=114wg.Add(1)go func(){//a=114mtx1.Lock()//加个锁fmt.Println("[1]-->: ",a)//输出一下设定的a的值//睡眠5s后再输出一下a的值,因为在2s后a的值已经在主线程中被更改了time.Sleep(5 * time.Second)fmt.Println("[2]-->: ",a)mtx1.Unlock()//解锁wg.Done()}()//睡眠2s后更改一下a的值time.Sleep(2 * time.Second)mtx2.Lock()//加个锁a = 514mtx2.Unlock()//解锁fmt.Println("[3]-->: ",a)wg.Wait()
}

修改的地方很简单,主线程中加的锁为另一个锁。

 输出为:

[root@vm10-0-0-63 gopath]# go  
[1]-->:  114
[3]-->:  514
[2]-->:  514
 

 

不难理解,因为使用的锁不一样,所以主线程修改a的值不用等分线程,主线程在睡眠2s后就直接修改了值,然后输出了[3]为514;

而分线程需要睡眠5s,在睡眠期间a的值已经被主线程改变了,所以输出了[2]同样为514。

 

 

小结

锁的作用范围为,

时间上是:具体某把锁的上锁到开锁这段时间;

流程上是:其他线程遇到具体某把锁在上锁时会阻塞;

变量上是:具体某把锁只管具体某把锁的事,上锁期间的其他变量不归锁管,其他线程想改还是能改

 

1.锁用什么定义方式都是一样的,无论是定义为全局变量还是定义在结构体中。

2.锁就是一个很普通的数据类型,不会有智能的更改识别,它只能保证自己上锁解锁,怎么用是程序员的事。

2..同一把锁在加锁到解锁这段时间内,其他线程中使用同一把锁进行的加锁操作会被阻塞。

2.在一把锁加锁期间内的变量,其他线程使用另一把锁加锁,无意义,仍能修改值。

 

本文发布于:2024-01-31 08:52:31,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170666235627329.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:作用
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23