go 并发学习-互斥锁
- 并发输出 inums 自增
-
- 使用互斥锁
-
- 使用锁时注意
- 上锁的资源独立函数
- 有些时候用读写锁
- 如果可以改为使用 channel
并发输出 inums 自增
编写代码
package main
import (
"fmt"
"time"
)
var inums = 0
func inumadd() int {
inums++
fmt.Println(inums)
return inums
}
func test() {
for {
inumadd()
time.Sleep(1000000000) //等待1秒
}
}
func main() {
go test()
go test()
go test()
go test()
go test()
go test()
test()
}
运行输出
API server listening at: 127.0.0.1:40291
1
3
4
5
6
2
7
9
8
13
14
12
10
11
并不能正常输出
- 互斥锁有两种操作,获取锁和释放锁
- 当有一个goroutine获取了互斥锁后,其它goroutine都不可以获取互斥锁,只能等待这个goroutine将互斥锁释放
- 互斥锁适用于读写操作数量差不多的情况
使用互斥锁
修改代码
package main
import (
"fmt"
"sync"
"time"
)
var inums = 0
var mutex sync.Mutex
func inumadd() int {
// 互斥锁
mutex.Lock()
defer mutex.Unlock()
inums++
fmt.Println(inums)
return inums
}
func test() {
for {
inumadd()
time.Sleep(1000000000) //等待1秒
}
}
func main() {
go test()
go test()
go test()
go test()
go test()
go test()
test()
}
结果
API server listening at: 127.0.0.1:31063
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
结果正常
使用锁时注意
上锁的资源独立函数
func inumadd() int {
// 互斥锁
mutex.Lock()
defer mutex.Unlock()
inums++
fmt.Println(inums)
// 比如在这 httpget,不推荐
// httpget(inums);
return inums
}
func test() {
for {
inumadd()
// 应该这里 httpget
httpget(inums);
time.Sleep(1000000000) //等待1秒
}
}
有些时候用读写锁
- 读写锁有四种操作 读上锁 读解锁 写上锁 写解锁
- 写锁最多有一个,读锁可以有多个(最大个数据说和CPU个数有关)
- 写锁的优先级高于读锁,这是因为为了防止读锁过多,写锁一直堵塞的情况发生
- 当有一个goroutine获得写锁时,其他goroutine不可以获得读锁或者写锁,知道这个写锁释放
- 当有一个goroutine获得读锁时,其他goroutine可以获得读锁,但是不能获得写锁。所以由此也可得知,如果当一个goroutine希望获取写锁时,不断地有其他goroutine在获得读锁和释放读锁会导致这个写锁一直处于堵塞状态,所以让写锁的优先级高于读锁可以避免这种情况,
- 读写锁适用于读多写少的情景。
如果可以改为使用 channel
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)