标签搜索
MemoryCloud Blog

Golang的原子属性

kennedy
2023-11-29 / 0 评论 / 28 阅读 / 正在检测是否收录...

lock

保证在执行A函数的时候,在A函数执行完毕之前不会执行B函数

==锁不能复制,复制后失去原有的效果== lock1 := lock

1.lock锁代码块(串行化降低性能)
var total int
var wg sync.WaitGroup
var lock sync.Mutex

func add() {
    defer wg.Done()
    for i := 0; i < 10000; i++ {
        lock.Lock()
        total += 1
        lock.Unlock()
    }
}

func sub() {
    defer wg.Done()
    for i := 0; i < 10000; i++ {
        lock.Lock()               //使用同一把锁
        total -= 1 
        lock.Unlock()             //释放锁
    }
}
func main() {
    wg.Add(2)
    go add()
    go sub()
    wg.Wait()
    fmt.Println(total)
}

lock逻辑是,执行lock的代码不会被其他协程影响,其余的协程进入cpu等待

func add() {
    defer wg.Done()
    for i := 0; i < 3; i++ {
        lock.Lock()
        total += 1
        fmt.Println("add")
        lock.Unlock()
    }
}

func sub() {
    defer wg.Done()
    for i := 0; i < 3; i++ {
        lock.Lock()
        total -= 1
        fmt.Println("sub")
        lock.Unlock()
    }
}
sub   //先执行lock
sub
sub
add
add
add   //等待sub执行结束
0
2. atomic包原子化
var total int32 //必须精准类型
func add() {
    defer wg.Done()
    for i := 0; i < 1000; i++ {
        atomic.AddInt32(&total, 1)
    }
}

func sub() {
    defer wg.Done()
    for i := 0; i < 1000; i++ {
        atomic.AddInt32(&total, -1)
    }
}
func main() {
    wg.Add(2)
    go add()
    go sub()
    wg.Wait()
    fmt.Println(total)
}
// 0
3.WMutex的读写

锁的本质是将代码串行化,影响性能,==即便设计锁也该尽量保证并行==

eg:两组协程,一组负责写数据,一组负责读数据;读协程应该并发,读写之间应该串行,读与读不能并行

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    var num int
    var rwlock sync.RWMutex
    var wg sync.WaitGroup
    wg.Add(2)
    go func() {    //写锁
        defer wg.Done()
        rwlock.Lock() //加写锁,写锁会防止别人的写锁获取,和读锁获取
        defer rwlock.Unlock()
        num = 12
    }()
    time.Sleep(1 * time.Second)  //保证写入先执行 

    go func() {   //读锁
        defer wg.Done()
        rwlock.RLock() //加读锁,读锁不会阻止别人的读
        defer rwlock.RUnlock()
        fmt.Println(num)
    }()
    wg.Wait()
}
//  12

加写锁会打断读锁

func main() {
    var rwlock sync.RWMutex
    var wg sync.WaitGroup
    wg.Add(6)
    go func() {
        time.Sleep(time.Second)
        defer wg.Done()
        rwlock.Lock() //加写锁,写锁会防止别人的写锁获取,和读锁获取
        defer rwlock.Unlock()
        fmt.Println("Begin Write!")
        time.Sleep(time.Second * 5)
    }()
    for i := 0; i < 5; i++ {
        go func() {
            defer wg.Done()
            for {
                rwlock.RLock() //加读锁,读锁不会阻止别人的读

                time.Sleep(time.Millisecond * 500)
                fmt.Println("red red red!")
                rwlock.RUnlock()
            }
        }()
    }
    wg.Wait()
}
red red red!
red red red!
red red red!
red red red!
red red red!
red red red!
red red red!
red red red!
red red red!
Begin Write!   //暂停读锁
1

评论

博主关闭了所有页面的评论