当前位置: 代码网 > it编程>前端脚本>Golang > Golang安全读写共享变量的方式详解

Golang安全读写共享变量的方式详解

2024年06月13日 Golang 我要评论
1. 使用互斥锁(mutex)互斥锁(mutex)是一种常用的同步原语,用于防止多个协程同时访问共享资源。package mainimport ( "fmt" "sync")var (

1. 使用互斥锁(mutex)

互斥锁(mutex)是一种常用的同步原语,用于防止多个协程同时访问共享资源。

package main
import (
    "fmt"
    "sync"
)
var (
    counter int
    mutex   sync.mutex
)
func increment(wg *sync.waitgroup) {
    defer wg.done()
    mutex.lock()
    counter++
    mutex.unlock()
}
func main() {
    var wg sync.waitgroup
    for i := 0; i < 1000; i++ {
        wg.add(1)
        go increment(&wg)
    }
    wg.wait()
    fmt.println("final counter:", counter)
}

2. 使用channel

go语言的核心理念之一就是“不通过共享内存来通信,而是通过通信来共享内存”。我们可以通过创建一个channel,然后通过发送和接收消息的方式来读写共享变量。这种方式在处理并发问题时非常有用,因为channel本身就提供了安全性。

package main
import (
    "fmt"
)
func increment(counter chan int, done chan bool) {
    for i := 0; i < 1000; i++ {
        value := <-counter
        value++
        counter <- value
    }
    done <- true
}
func main() {
    counter := make(chan int, 1)
    counter <- 0
    done := make(chan bool)
    for i := 0; i < 10; i++ {
        go increment(counter, done)
    }
    for i := 0; i < 10; i++ {
        <-done
    }
    fmt.println("final counter:", <-counter)
}

3. 读写锁(sync.rwmutex)

如果程序中的读操作远多于写操作,那么使用读写锁可能会比互斥锁更有效率。读写锁允许多个协程同时读取变量,但是只允许同一时刻只有一个协程进行写入操作。

package main
import (
    "fmt"
    "sync"
)
var (
    counter int
    rwmutex sync.rwmutex
)
func read(wg *sync.waitgroup) {
    defer wg.done()
    rwmutex.rlock()
    fmt.println("counter:", counter)
    rwmutex.runlock()
}
func write(wg *sync.waitgroup) {
    defer wg.done()
    rwmutex.lock()
    counter++
    rwmutex.unlock()
}
func main() {
    var wg sync.waitgroup
    for i := 0; i < 10; i++ {
        wg.add(1)
        go read(&wg)
    }
    for i := 0; i < 10; i++ {
        wg.add(1)
        go write(&wg)
    }
    wg.wait()
}

4. 原子操作(sync/atomic包)

对于一些简单的数值或者布尔类型,我们可以使用原子操作来读写共享变量。

package main
import (
    "fmt"
    "sync"
    "sync/atomic"
)
var counter int64
func increment(wg *sync.waitgroup) {
    defer wg.done()
    atomic.addint64(&counter, 1)
}
func main() {
    var wg sync.waitgroup
    for i := 0; i < 1000; i++ {
        wg.add(1)
        go increment(&wg)
    }
    wg.wait()
    fmt.println("final counter:", counter)
}

5. sync.once

如果共享变量只需要被初始化一次,可以使用sync.once来确保初始化的并发安全性。

package main
import (
    "fmt"
    "sync"
)
var (
    once sync.once
    initvalue int
)
func initialize() {
    fmt.println("initializing...")
    initvalue = 42
}
func dosomething() {
    once.do(initialize)
    fmt.println("value:", initvalue)
}
func main() {
    var wg sync.waitgroup
    for i := 0; i < 10; i++ {
        wg.add(1)
        go func() {
            defer wg.done()
            dosomething()
        }()
    }
    wg.wait()
}

最后给大家推荐一个linuxc/c++高级架构系统教程的学习资源与课程,可以帮助你有方向、更细致地学习c/c++后端开发,具体内容请见 https://xxetb.xetslk.com/s/1o04ub

到此这篇关于golang安全读写共享变量的方式的文章就介绍到这了,更多相关golang安全读写共享变量内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com