golang-锁问题1-5
目录
1.说下Go中的锁有哪些?三种锁,互斥锁,读写锁,还有map的安全的锁?
互斥锁:同一时刻只能有一个协程获取这把锁,其他的只能等待
读写锁:依赖与互斥锁实现,多个协程可以同时获取读锁,读取资源不限制。但是同一时刻只能一个协程获取写锁
map安全锁:原生map是非并发安全的,所以为了保证map的并发安全,最简单的方式就是给map加锁。
sync.Map是加过锁的,可以直接安全使用
1.1互斥锁
var x int64
var wg sync.WaitGroup
var lock sync.Mutex
func add() {
for i := 0; i < 5000; i++ {
lock.Lock() // 加锁
x = x + 1
lock.Unlock() // 解锁
}
wg.Done()
}
func main() {
wg.Add(2)
go add()
go add()
wg.Wait()
fmt.Println(x)
}
1.2读写锁
var (
x int64
wg sync.WaitGroup
rwlock sync.RWMutex
)
func write() {
rwlock.Lock() // 加写锁
x = x + 1
time.Sleep(10 * time.Millisecond) // 假设读操作耗时10毫秒
rwlock.Unlock() // 解写锁
wg.Done()
}
func read() {
rwlock.RLock() // 加读锁
time.Sleep(time.Millisecond) // 假设读操作耗时1毫秒
rwlock.RUnlock() // 解读锁
wg.Done()
}
读写锁,可以同时获取多个读锁,但是只能同时获取一把写锁。
读写锁当有⼀个协程在等待写锁时,其他协程是不能获得读锁的,让写锁优先获取,⽽A 的读锁⼜要求C 调⽤完成,因此死锁。
var mu sync.RWMutex
var count int
func main() {
go A()
time.Sleep(2 * time.Second)
mu.Lock()
defer mu.Unlock()
count++
fmt.Println(count)
}
func A() {
mu.RLock()
defer mu.RUnlock()
B()
}
func B() {
time.Sleep(3 * time.Second)
C()
}
func C() {
mu.RLock()
defer mu.RUnlock()
}
1.3map安全锁
这个字典类型提供了一些常用的键值存取操作方法,并保证了这些操作的并发安全
var ma sync.Map //该类型是开箱即用,只需要声明既可
ma.Store("key", "value") // 存储值
ma.Delete("key") //删除值
ma.LoadOrStore("key", "value")// 获取值,如果没有则存储
fmt.Println(ma.Load("key"))//获取值
//遍历
ma.Range(func(key, value interface{}) bool {
fmt.Printf("key:%s ,value:%s \n", key, value)
//如果返回:false,则退出循环,
return true
})
2.互斥锁,读写锁,死锁问题是怎么解决
互斥锁
互斥锁就是互斥变量mutex,用来锁住临界区的.
条件锁就是条件变量,当进程的某些资源要求不满足时就进入休眠,也就是锁住了。当资源被分配到了,条件锁打开,进程继续运行;读写锁,也类似,用于缓冲区等临界资源能互斥访问的。
读写锁
通常有些公共数据修改的机会很少,但其读的机会很多。并且在读的过程中会伴随着查找,给这种代码加锁会降低我们的程序效率。读写锁可以解决这个问题。
死锁
一般情况下,如果同一个线程先后两次调用lock,在第二次调用时,由于锁已经被占用,该线程会挂起等待别的线程释放锁,然而锁正是被自己占用着的,该线程又被挂起而没有机会释放锁,因此就永远处于挂起等待状态了,这叫做死锁(Deadlock)。 另外一种情况是:若线程A获得了锁1,线程B获得了锁2,这时线程A调用lock试图获得锁2,结果是需要挂起等待线程B释放锁2,而这时线程B也调用lock试图获得锁1,结果是需要挂起等待线程A释放锁1,于是线程A和B都永远处于挂起状态了。
3.Golang中除了加Mutex锁以外还有哪些方式安全读写共享变量?
Golang中Goroutine 可以通过 Channel 进行安全读写共享变量。
4.go的锁如何实现,用了什么cpu指令
原理:博客地址待填写
Mutex对外提供两个方法
Lock():加锁方法
Unlock():解锁方法
cpu指令:PAUSE暂停停顿
5.读写锁或者互斥锁读的时候能写吗?
不能。 可以同时读,但是读-写,写-写都是互斥的。
Go中读写锁包括读锁和写锁,多个读线程可以同时访问共享数据;写线程必须等待所有读线程都释放锁以后,才能取得锁;同样的,读线程必须等待写线程释放锁后,才能取得锁,也就是说读写锁要确保的是如下互斥关系,可以同时读,但是读-写,写-写都是互斥的。
选择了IT,必定终身学习