sync.Mutex
package main
import (
"fmt"
"sync"
"time"
)
func doSomeThingWithLock(lock *sync.Mutex, name string) {
lock.Lock()
defer lock.Unlock()
fmt.Println("doSomethingWithLock", name)
time.Sleep(time.Second * 2)
fmt.Println(name, "leave")
}
func main() {
var lock sync.Mutex
//a协程
go doSomeThingWithLock(&lock, "a")
//b协程
go doSomeThingWithLock(&lock, "b")
time.Sleep(time.Second * 10)
}
假设,如果先进入了a,则lock.Lock()加锁, 直到a运行结束defer lock.Unlock()之后,其他线程(b)(协程???or 轻线程???)才能获得这个锁。
sync.RWMutex(读写锁)
- RLock() 读加锁
- RUnlock() 读解锁
- Lock() 写加锁
- Unlock() 写解锁
1、读写锁互斥
2、同一时间段内,只能有一个goroutine获得写锁
3、同一时间段内,可以有多个goroutine获得读锁
package main
import (
"fmt"
"sync"
"time"
)
func read(i int, rwlock *sync.RWMutex) {
rwlock.RLock()
defer rwlock.RUnlock()
fmt.Println("读锁", i)
time.Sleep(time.Second)
}
func write(i int, rwlock *sync.RWMutex) {
rwlock.Lock()
defer rwlock.Unlock()
fmt.Println("写锁", i, time.Now())
time.Sleep(time.Second * 2)
}
func main() {
var rwlock sync.RWMutex
for i := 0; i < 5; i++ {
go read(i, &rwlock)
}
for i := 0; i < 5; i++ {
go write(i, &rwlock)
}
time.Sleep(time.Second * 100)
}
result:
读锁 0
读锁 4
写锁 1 2021-06-21 18:01:51.478746 +0800 CST m=+1.005293905
读锁 2
读锁 3
读锁 1
写锁 4 2021-06-21 18:01:54.487004 +0800 CST m=+4.013535880
写锁 2 2021-06-21 18:01:56.491133 +0800 CST m=+6.017654130
写锁 3 2021-06-21 18:01:58.493108 +0800 CST m=+8.019618534
写锁 0 2021-06-21 18:02:00.494122 +0800 CST m=+10.020621713
此段代码,打印出“写锁"之后,无论下面打印”读锁"还是“写锁"肯定要等2以上秒
WaitGroup (并发等待组)
// 添加等待数量
func (wg *WaitGroup)Add(delta int)
// 等待数量减1
func(wg *WaitGroup)Done()
//使此goroutine等待
func(wg *WaitGroup)Wait()
sync.WaitGroup适用于执行批量操作,等待所有goroutine执行结束后统一返回结果。
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
func main() {
wg.Add(5)
fmt.Println(time.Now())
for i := 0; i < 5; i++ {
go func(i int) {
defer wg.Done()
fmt.Println(i)
time.Sleep(time.Second * 2)
}(i)
}
wg.Wait()
fmt.Println("main end", time.Now())
}
sync.Map (并发安全map)
// 根据key 获取 value
func (m *Map)Load(key interface{})(value interface{}, ok bool)
// 设置key-value
func (m *Map)Store(key, value interface{})
// 如果key存在则返回对应的value,否则设置key-value
func (m *Map)LoadOrStore(key, value interface{})(actual interface{}, loaded bool)
// 删除一个key以及对应的值
func (m *Map)Delete(key interface{})
//无序遍历
func (m *Map)Range(f func(key, value interface{}) bool)