互斥锁
其中Mutex为互斥锁,Lock()加锁,Unlock()解锁,使用Lock()加锁后,便不能再次对其进行加锁,直到利用Unlock()解锁对其解锁后,才能再次加锁.适用于读写不确定场景,即读写次数没有明显的区别,并且只允许只有一个读或者写的场景,所以该锁叶叫做全局锁。
func (m *Mutex) Unlock()用于解锁m,如果在使用Unlock()前未加锁,就会引起一个运行错误.已经锁定的Mutex并不与特定的goroutine相关联,这样可以利用一个goroutine对其加锁,再利用其他goroutine对其解锁。
package main
import(
"fmt"
"time"
"sync"
"math/rand"
)
var lock sync.Mutex
func main() {
testMap()
}
func testMap() {
var a map[int]int
a = make(map[int]int, 5)
a[8] = 10
a[3] = 10
a[2] = 10
a[1] = 10
a[18] = 10
for i := 0; i < 2; i++ {
go func(b map[int]int) {
lock.Lock()
b[8] = rand.Intn(100)
lock.Unlock()
}(a)
}
lock.Lock()
fmt.Println(a)
lock.Unlock()
time.Sleep(time.Second)
fmt.Println(a)
}
输出如下:
PS E:\golang\go_pro\src\safly> go run demo.go
map[3:10 2:10 1:10 18:10 8:10]
map[2:10 1:10 18:10 8:87 3:10]
PS E:\golang\go_pro\src\safly>
我们利用了time.Sleep(time.Second)这个进行的延迟,goroute执行完毕,就进行输出,结果是进行了map的修改
读写锁
读写锁实际是一种特殊的自旋锁,它把对共享资源的访问者划分成读者和写者,读者只对共享资源进行读访问,写者则需要对共享资源进行写操作。这种锁相对于自旋锁而言,能提高并发性,因为在多处理器系统中,它允许同时有多个读者来访问共享资源,最大可能的读者数为实际的逻辑cpu数。写者是排他性的,一个读写锁同时只能有一个写者或多个读者(与cpu数相关),但不能同时既有读者又有写者。
1、可以随便读,多个goroutine同时读
package main
import(
// "fmt"
"time"
"sync"
)
var m *sync.RWMutex
func main() {
m = new(sync.RWMutex)
// 多个同时读
go read(1)
go read(2)
time.Sleep(2*time.Second)
}
func read(i int) {
println(i,"read start")
m.RLock()
println(i,"reading")
time.Sleep(1*time.Second)
m.RUnlock()
println(i,"read over")
}
输出如下:
PS E:\golang\go_pro\src\safly> go run demo.go
1 read start
1 reading
1 read over
2 read start
2 reading
2 read over
可以看出1 读还没有结束,2已经在读