0

0

使用 Go 语言的 Channel 替代互斥锁 (Mutex)

碧海醫心

碧海醫心

发布时间:2025-07-19 18:28:38

|

340人浏览过

|

来源于php中文网

原创

使用 go 语言的 channel 替代互斥锁 (mutex)

本文旨在阐述如何在 Go 语言中使用 Channel 来实现互斥锁的功能。Channel 不仅可以进行数据传递,还具备同步机制,能确保 Goroutine 之间的状态同步。通过示例代码,我们将展示如何利用 Channel 的特性来避免竞态条件,并提供使用空结构体 Channel 优化内存占用的方法。

在并发编程中,互斥锁(Mutex)是一种常用的同步原语,用于保护共享资源,防止多个 Goroutine 同时访问造成数据竞争。然而,Go 语言提供的 Channel 机制,在某些情况下,可以作为互斥锁的替代方案,提供更简洁、更高效的并发控制方式。

Channel 的核心在于其同步特性。当一个 Goroutine 尝试从一个空的 Channel 接收数据时,它会被阻塞,直到有其他 Goroutine 向该 Channel 发送数据。同样,当一个 Goroutine 尝试向一个已满的 Channel 发送数据时,它也会被阻塞,直到有其他 Goroutine 从该 Channel 接收数据。 这种阻塞和唤醒机制,天然地提供了同步能力。

我们可以利用带缓冲的 Channel (Buffered Channel) 来模拟互斥锁的行为。 创建一个容量为 1 的 Channel,可以将其视为一个“许可证”。 Goroutine 只有成功从 Channel 接收到数据,才能获得访问共享资源的权限;访问完成后,再将数据发送回 Channel,释放“许可证”,允许其他 Goroutine 访问。

以下是一个使用 Channel 替代 Mutex 的示例:

package main

import "fmt"

var global int = 0
var c = make(chan int, 1)

func thread1() {
    <-c // 从 Channel 接收数据,获取“许可证”
    global = 1
    fmt.Println("Thread 1: global =", global)
    c <- 1 // 将数据发送回 Channel,释放“许可证”
}

func thread2() {
    <-c // 从 Channel 接收数据,获取“许可证”
    global = 2
    fmt.Println("Thread 2: global =", global)
    c <- 1 // 将数据发送回 Channel,释放“许可证”
}

func main() {
    c <- 1 // 初始化 Channel,放入一个“许可证”
    go thread1()
    go thread2()

    // 等待 Goroutine 执行完成,避免程序过早退出
    var input string
    fmt.Scanln(&input)
}

在这个例子中,c 是一个容量为 1 的 chan int。main 函数首先向 c 发送一个值 1,相当于初始化了“许可证”。 thread1 和 thread2 在访问 global 变量之前,都必须先从 c 接收数据,获得“许可证”,访问完成后,再将数据发送回 c,释放“许可证”。 这样就保证了 global 变量在同一时刻只能被一个 Goroutine 访问,避免了竞态条件。

使用空结构体 Channel 优化内存占用

英特尔AI工具
英特尔AI工具

英特尔AI与机器学习解决方案

下载

在上述示例中,我们使用了 chan int,但实际上,我们并不关心 Channel 中传递的具体数值,只需要利用 Channel 的同步特性即可。 因此,可以使用 chan struct{} 来替代 chan int,以减少内存占用。 空结构体 struct{} 不占用任何内存空间,使用 chan struct{} 可以有效地降低程序的内存消耗。

修改后的代码如下:

package main

import "fmt"

var global int = 0
var c = make(chan struct{}, 1)

func thread1() {
    <-c // 从 Channel 接收数据,获取“许可证”
    global = 1
    fmt.Println("Thread 1: global =", global)
    c <- struct{}{} // 将数据发送回 Channel,释放“许可证”
}

func thread2() {
    <-c // 从 Channel 接收数据,获取“许可证”
    global = 2
    fmt.Println("Thread 2: global =", global)
    c <- struct{}{} // 将数据发送回 Channel,释放“许可证”
}

func main() {
    c <- struct{}{} // 初始化 Channel,放入一个“许可证”
    go thread1()
    go thread2()

    // 等待 Goroutine 执行完成,避免程序过早退出
    var input string
    fmt.Scanln(&input)
}

在这个修改后的版本中,c 的类型变为 chan struct{},并且我们使用 struct{}{} 来初始化 Channel 和发送数据。 这与之前的版本功能相同,但内存占用更小。

注意事项和总结

  • 使用 Channel 替代 Mutex 是一种有效的并发控制手段,尤其适用于需要进行数据传递和同步的场景。
  • 使用容量为 1 的带缓冲 Channel 可以模拟互斥锁的行为。
  • 使用 chan struct{} 可以有效地降低程序的内存消耗。
  • 需要注意的是,Channel 的使用也可能引入死锁等问题,需要仔细设计并发逻辑,避免出现循环等待的情况。
  • 在实际应用中,应根据具体场景选择合适的并发控制机制,Mutex 和 Channel 各有优缺点,需要权衡考虑。

总而言之,理解 Channel 的同步机制,并灵活运用,可以编写出更简洁、更高效的并发程序。

相关专题

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

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

194

2025.06.09

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

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

186

2025.07.04

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

312

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

522

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

49

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

190

2025.08.29

Golang channel原理
Golang channel原理

本专题整合了Golang channel通信相关介绍,阅读专题下面的文章了解更多详细内容。

241

2025.11.14

golang channel相关教程
golang channel相关教程

本专题整合了golang处理channel相关教程,阅读专题下面的文章了解更多详细内容。

320

2025.11.17

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

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

74

2025.12.31

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

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

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