-
1.互斥锁:sync.Mutex
当多个线程同时修改一个公共资源时,需要进行同步控制
import "sync"
var {
mu sync.Mutex
balance int
}
func Deposit(amount int){
mu.lock()
defer mu.Unlock()
balance = balance + amount
}
func Balance() int{
mu.lock()
b := balance
mu.Unlock()
return b
}
代码中对临界资源的修改和读取使用互斥锁进行保护,防止并发数据异常。
-
2.读写互斥锁:sync.RWMutex
调用RLock和RUnlock方法来分别获取和释放一个读锁(也称为共享锁)。通过Lock和Unlock来分别获取和释放一个写锁(也称为互斥锁)。
import "sync"
var {
mu sync.RWMutex
balance int
}
func Deposit(amount int){
mu.lock()
defer mu.Unlock()
balance = balance + amount
}
func Balance() int{
mu.Rlock()
b := balance
mu.RUnlock()
return b
}
-
3.延迟初始化:sync.Once
sync.Once可以保证一个Once实例的Do方法只会执行一次,无论Do里的func有多个或者一个,利用这个特性来实现设计模式里的单例模式,注意要确保执行Do的Once实例是同一个。
type singleton struct{}
var {
ins *singleton
once sync.Once
}
func GetIns() *singleton {
once.Do(func(){
ins = &singleton{}
})
return ins
}
这是单例模式在go语言下最优雅的写法
-
4.并发控制:sync.WaitGroup
开发过程中,经常task之间的同步问题。例如,多个子task并发完成一部分任务,主task等待他们最后结束。
下面代码如果不加WaitGroup,可能不会打印出数字,因为还没等协程执行主线程已经返回,导致协程不会执行。
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
func PrintInt(num int) {
fmt.Println(num)
wg.Done()
}
func main() {
wg.Add(10)
for i := 0; i < 10; i++ {
go PrintInt(i)
}
wg.Wait()
}
注意
WaitGroup变量定义后,是不允许被拷贝的,即不允许作为函数参数或者赋值给其他变量。