自旋锁和互斥锁实例_Golang并发编程之互斥锁、读写锁详解

点击上方 "程序员小乐"关注, 星标或置顶一起成长

每天凌晨00点00分, 第一时间与你相约

每日英文

It's so hard to tell someone how you really feel about them when you're too afraid of losing what you already have.

有时候,要坦白对某个人的感觉真的太难了,因为太害怕连现在这种关系都失去。

每日掏心话

我们不要去做一个单纯优秀的人,而是要去做一个不可替代的人。

来自:我爱吃炒鸡 | 责编:乐乐

链接:my.oschina.net/chinaliuhan/blog/3168384

5e92e389d133f7fadadcff7a16b52b21.png

程序员小乐(ID:study_tech)第 829 次推文 图片来自百度

往日回顾:“微信遗嘱”功能开通,网友体验后发现...如果突然离世,你的QQ、支付宝等怎么办?

正文

我们对Go语言所提供的与锁有关的API进行说明。这包括了互斥锁和读写锁。我们在第6章描述过互斥锁,但却没有提到过读写锁。这两种锁对于传统的并发程序来说都是非常常用和重要的。

一、互斥锁

互斥锁是传统的并发程序对共享资源进行访问控制的主要手段。它由标准库代码包sync中的Mutex结构体类型代表。sync.Mutex类型(确切地说,是*sync.Mutex类型)只有两个公开方法——Lock和Unlock。顾名思义,前者被用于锁定当前的互斥量,而后者则被用来对当前的互斥量进行解锁。 类型sync.Mutex的零值表示了未被锁定的互斥量。也就是说,它是一个开箱即用的工具。我们只需对它进行简单声明就可以正常使用了,就像这样: 代码如下:

var mutex sync.Mutex
mutex.Lock()

在我们使用其他编程语言(比如C或Java)的锁类工具的时候,可能会犯的一个低级错误就是忘记及时解开已被锁住的锁,从而导致诸如流程执行异常、线程执行停滞甚至程序死锁等等一系列问题的发生。

然而,在Go语言中,这个低级错误的发生几率极低。其主要原因是有defer语句的存在。 我们一般会在锁定互斥锁之后紧接着就用defer语句来保证该互斥锁的及时解锁。请看下面这个函数: 代码如下:

var mutex sync.Mutex
func write() {
mutex.Lock()
defer mutex.Unlock()
// 省略若干条语句
}

函数write中的这条defer语句保证了在该函数被执行结束之前互斥锁mutex一定会被解锁。这省去了我们在所有return语句之前以及异常发生之时重复的附加解锁操作的工作。在函数的内部执行流程相对复杂的情况下,这个工作量是不容忽视的,并且极易出现遗漏和导致错误。

所以,这里的defer语句总是必要的。在Go语言中,这是很重要的一个惯用法。我们应该养成这种良好的习惯。 对于同一个互斥锁的锁定操作和解锁操作总是应该成对的出现。如果我们锁定了一个已被锁定的互斥锁,那么进行重复锁定操作的Goroutine将会被阻塞,直到该互斥锁回到解锁状态。请看下面的示例: 代码如下:

func repeatedlyLock() {
var mutex sync.Mutex
fmt.Println("Lock the lock. (G0)")
mutex.Lock()
fmt.Println("The lock is locked. (G0)")
for i := 1; i <= 3; i++ {
go func(i int) {
fmt.Printf("Lock the lock. (G%d)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值