Golang 中的互斥锁是什么?

简介: #go#programming#beginners#architecture

当您构建 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”值以递增它,然后更新变量。

如果两个(或更多)Goroutine 大约在同一时间复制该值,它们将不会意识到其他 Goroutine 所做的更新。

例如:假设值为“200”;两个 Goroutines 中的每一个都会添加“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 数量完全相同。

目录
相关文章
|
5天前
|
安全 Go
Golang深入浅出之-互斥锁(sync.Mutex)与读写锁(sync.RWMutex)
【4月更文挑战第23天】Go语言并发编程中,`sync.Mutex`和`sync.RWMutex`是保证线程安全的关键。互斥锁确保单个goroutine访问资源,而读写锁允许多个读者并发访问。常见问题包括忘记解锁、重复解锁以及混淆锁类型。使用`defer`可确保解锁,读写锁不支持直接升级或降级,需释放后再获取。根据读写模式选择合适锁以避免性能下降和竞态条件。理解并正确使用锁是编写并发安全程序的基础。
25 3
|
5天前
|
存储 安全 Go
Golang分段锁
Golang分段锁
36 0
|
5天前
|
存储 Go
浅谈Golang互斥锁sync.Mutex
浅谈Golang互斥锁sync.Mutex
14 0
|
5天前
|
存储 编译器 Go
Golang底层原理剖析之互斥锁sync.Mutex
Golang底层原理剖析之互斥锁sync.Mutex
37 0
|
7月前
|
Go
Golang 语言标准库 sync 包的 RWMutex 读写互斥锁怎么使用?
Golang 语言标准库 sync 包的 RWMutex 读写互斥锁怎么使用?
28 0
|
10月前
|
安全 Go
golang中的互斥锁和管道
golang中的互斥锁和管道
|
10月前
|
存储 Go 调度
golang 锁原理剖析,你值得收藏
golang 锁原理剖析,你值得收藏
|
5天前
|
监控 算法 Go
Golang深入浅出之-Go语言中的服务熔断、降级与限流策略
【5月更文挑战第4天】本文探讨了分布式系统中保障稳定性的重要策略:服务熔断、降级和限流。服务熔断通过快速失败和暂停故障服务调用来保护系统;服务降级在压力大时提供有限功能以保持整体可用性;限流控制访问频率,防止过载。文中列举了常见问题、解决方案,并提供了Go语言实现示例。合理应用这些策略能增强系统韧性和可用性。
52 0
|
5天前
|
分布式计算 Java Go
Golang深入浅出之-Go语言中的分布式计算框架Apache Beam
【5月更文挑战第6天】Apache Beam是一个统一的编程模型,适用于批处理和流处理,主要支持Java和Python,但也提供实验性的Go SDK。Go SDK的基本概念包括`PTransform`、`PCollection`和`Pipeline`。在使用中,需注意类型转换、窗口和触发器配置、资源管理和错误处理。尽管Go SDK文档有限,生态系统尚不成熟,且性能可能不高,但它仍为分布式计算提供了可移植的解决方案。通过理解和掌握Beam模型,开发者能编写高效的数据处理程序。
141 1
|
5天前
|
缓存 测试技术 持续交付
Golang深入浅出之-Go语言中的持续集成与持续部署(CI/CD)
【5月更文挑战第5天】本文介绍了Go语言项目中的CI/CD实践,包括持续集成与持续部署的基础知识,常见问题及解决策略。测试覆盖不足、版本不一致和构建时间过长是主要问题,可通过全面测试、统一依赖管理和利用缓存优化。文中还提供了使用GitHub Actions进行自动化测试和部署的示例,强调了持续优化CI/CD流程以适应项目需求的重要性。
56 1
http://www.vxiaotou.com