0

0

Go 并发编程:使用 Mutex 保护共享变量

DDD

DDD

发布时间:2025-09-03 21:55:20

|

209人浏览过

|

来源于php中文网

原创

go 并发编程:使用 mutex 保护共享变量

在 Go 并发编程中,多个 Goroutine 同时访问和修改共享变量时,如果没有适当的同步机制,就会出现竞态条件,导致程序行为不可预测。本文将深入探讨如何使用 sync.Mutex 互斥锁来解决这个问题,并提供代码示例,帮助开发者构建安全可靠的并发程序。

使用 sync.Mutex 保护共享变量

sync.Mutex 是 Go 语言标准库 sync 包提供的一种互斥锁,用于保护临界区,确保同一时刻只有一个 Goroutine 可以访问被保护的共享资源。

以下是一个使用 sync.Mutex 封装计数器的示例:

package main

import (
    "fmt"
    "net/http"
    "sync"
)

type Counter struct {
    mu  sync.Mutex
    x   int64
}

func (c *Counter) Add(x int64) {
    c.mu.Lock() // 获取锁
    c.x += x
    c.mu.Unlock() // 释放锁
}

func (c *Counter) Value() (x int64) {
    c.mu.Lock() // 获取锁
    x = c.x
    c.mu.Unlock() // 释放锁
    return
}

func makeHomeHandler() func(http.ResponseWriter, *http.Request) {
    var views Counter
    return func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Counting %s, %d so far.\n", r.URL.Path[1:], views.Value())
        views.Add(1)
    }
}

func main() {
    http.HandleFunc("/", makeHomeHandler())
    fmt.Println("Server listening on port 8080")
    http.ListenAndServe(":8080", nil)
}

在这个例子中,Counter 结构体包含一个 sync.Mutex 类型的 mu 字段和一个 int64 类型的 x 字段,用于存储计数器的值。Add 和 Value 方法都使用 mu.Lock() 获取锁,并在方法结束前使用 mu.Unlock() 释放锁。这样就保证了对 x 字段的并发访问是安全的。

注意事项:

千图设计室AI海报
千图设计室AI海报

千图网旗下的智能海报在线设计平台

下载
  • 务必在访问共享变量之前获取锁,并在访问完成后释放锁。
  • 避免在持有锁的情况下执行耗时操作,以免阻塞其他 Goroutine。
  • 可以使用 defer 语句来确保锁的释放,即使发生 panic 也能保证锁最终被释放。

使用 http.Handler 接口简化代码

对于 HTTP 处理程序,可以定义一个实现了 http.Handler 接口的类型,将互斥锁和计数器封装在类型内部,从而简化代码结构。

以下是一个使用 http.Handler 接口的示例:

package main

import (
    "fmt"
    "net/http"
    "sync"
)

type homeHandler struct {
    mu    sync.Mutex
    views int64
}

func (h *homeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    h.mu.Lock()
    defer h.mu.Unlock()
    fmt.Fprintf(w, "Counting %s, %d so far.\n", r.URL.Path[1:], h.views)
    h.views++
}

func main() {
    http.Handle("/", new(homeHandler))
    fmt.Println("Server listening on port 8080")
    http.ListenAndServe(":8080", nil)
}

在这个例子中,homeHandler 结构体实现了 http.Handler 接口的 ServeHTTP 方法。在 ServeHTTP 方法中,使用 h.mu.Lock() 获取锁,并使用 defer h.mu.Unlock() 确保锁的释放。这样就保证了对 h.views 字段的并发访问是安全的。

总结:

  • sync.Mutex 是 Go 语言中用于保护共享变量的常用工具
  • 通过封装计数器或使用 http.Handler 接口,可以简化代码结构,提高代码的可读性和可维护性。
  • 在并发编程中,务必注意对共享资源的同步访问,避免竞态条件,确保程序行为的正确性。

相关专题

更多
golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

193

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

186

2025.07.04

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

989

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

50

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

228

2025.12.29

http500解决方法
http500解决方法

http500解决方法有检查服务器日志、检查代码错误、检查服务器配置、检查文件和目录权限、检查资源不足、更新软件版本、重启服务器或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

270

2023.11.09

http请求415错误怎么解决
http请求415错误怎么解决

解决方法:1、检查请求头中的Content-Type;2、检查请求体中的数据格式;3、使用适当的编码格式;4、使用适当的请求方法;5、检查服务器端的支持情况。更多http请求415错误怎么解决的相关内容,可以阅读下面的文章。

386

2023.11.14

HTTP 503错误解决方法
HTTP 503错误解决方法

HTTP 503错误表示服务器暂时无法处理请求。想了解更多http错误代码的相关内容,可以阅读本专题下面的文章。

1093

2024.03.12

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

65

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 3.2万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号