【GO】6.锁

  • 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变量定义后,是不允许被拷贝的,即不允许作为函数参数或者赋值给其他变量。

猜你喜欢

转载自blog.csdn.net/chen_peng7/article/details/89739325