Golang 中的互斥锁是什么?

简介: #去#编程#初学者#建筑学

当您构建 Golang 程序时,您几乎总会发现 Goroutines 的用途。

Goroutines 功能强大且通常易于使用,但是,如果您需要修改 Goroutines 之间共享的某些数据,那么您可能会遇到数据完整性方面的问题。

在本文中,我们将了解什么是“互斥体”以及如何使用它。

什么是互斥体?

在Golang中;Goroutine 本质上是一个放在后台队列中并在资源可用时并发执行的函数。

package main
import (
    "fmt"
    "sync"
)
var NUM_PROCESSED = 0
func countNumProcessed(wg *sync.WaitGroup) {
    defer wg.Done()
    NUM_PROCESSED++
}
func main() {
    var wg sync.WaitGroup
    for i := 0; i < 500; i++ {
        wg.Add(1)
        go countNumProcessed(&wg)
    }
    wg.Wait()
    fmt.Println(NUM_PROCESSED)
}

如果我们删除“go”关键字,则对“countNumProcessed”的每个函数调用都会阻塞循环并等待该函数完成后再继续循环。

当您使用“go”关键字时,这些函数将同时运行。这使得 2 个或更多函数可以同时修改变量。

如果您运行此代码几次 - 您会注意到总计数会波动。

这是因为每个 Goroutine 在几纳秒内复制内存中的“NUM_PROCESSED”值以递增它,然后更新变量。

如果两个(或更多)Goroutines 大约在同一时间复制该值。例如:假设设置为“200”,那么每个都会添加“1”即“201”。因此,“NUM_PROCESSED”的值将变为“201”而不是“202”。

这就是互斥体派上用场的地方。互斥锁会在进程中创建一把“锁”——这样一次只有一个 Goroutine 可以更新“NUM_PROCESSED”。

然后其他 Goroutines 将暂停,直到锁被释放。这与队列非常相似 - 当每个 Goroutine 释放锁时,下一个 Goroutine 会获取新锁,并且该过程将继续,直到所有排队的 Goroutine 完成更新“NUM_PROCESSED”。

互斥体示例

我们可以修改上面的代码来引入一个Mutex,如下所示:

package main
import (
    "fmt"
    "sync"
)
var NUM_PROCESSED = 0
var MUTEX sync.Mutex
func countNumProcessed(wg *sync.WaitGroup) {
    defer wg.Done()
    MUTEX.Lock()
    NUM_PROCESSED++
    MUTEX.Unlock()
}
func main() {
    var wg sync.WaitGroup
    for i := 0; i < 500; i++ {
        wg.Add(1)
        go countNumProcessed(&wg)
    }
    wg.Wait()
    fmt.Println(NUM_PROCESSED)
}

您会注意到上面的代码,无论您运行这个函数多少次,它总是会打印“500”:这与 for 循环中创建的 goroutine 数量完全相同。

相关文章
|
6月前
|
安全 Go 持续交付
深入Golang之Mutex
深入Golang之Mutex
72 0
|
6月前
|
Go
浅谈Golang并发控制WaitGroup
浅谈Golang并发控制WaitGroup
56 0
|
3月前
|
SQL 安全 Java
golang为什么不支持可重入锁?
本文对比分析了Java与Go语言中锁机制的不同。在Java中,无论是`synchronized`关键字还是`ReentrantLock`都支持可重入特性,通过维护一个计数器来跟踪锁的嵌套级别,确保同一线程可以多次获取同一把锁而不会造成死锁。然而,Go语言的`sync.Mutex`并不支持这一特性,其设计理念认为可重入锁往往指向代码设计问题,鼓励开发者重构代码以避免此类需求。文章进一步解释了这种设计理念背后的原因,并提供了替代方案示例。总体而言,Go语言试图从设计层面避免潜在的代码问题,尽管这可能会增加一定的开发复杂性。
golang为什么不支持可重入锁?
|
6月前
|
Go
Golang 中的互斥锁是什么?
# go # programming # beginners # architecture
|
6月前
|
安全 Linux Go
golang面试:golang并发与多线程(三)
golang面试:golang并发与多线程(三)
106 0
|
安全 Go
golang中的互斥锁和管道
golang中的互斥锁和管道
|
存储 Go 调度
golang 锁原理剖析,你值得收藏
golang 锁原理剖析,你值得收藏
|
Go 数据安全/隐私保护
golang mutex两加两解助你实现高并发控制
golang mutex两加两解助你实现高并发控制