php 多线程 互斥 锁,Golang学习笔记之互斥锁(Mutex)

Go语言包中的sync包提供了两种锁,互斥锁(sync.Mutex)和读写锁(sync.RWMutex)

这一篇博文我们只说一下互斥锁。

Mutex是一个互斥锁,可以创建为其他结构体的字段;零值为解锁状态。Mutex类型的锁和线程无关,可以由不同的线程加锁和解锁。

• 它只有两个公开方法:Lock()加锁,unlock()解锁。

• 在同一个协程中加锁后,不能再继续对其加锁,否则会panic。只有在解锁之后才能再次加锁。

• 只允许只有一个读或者写的场景

• 在使用Unlock()解锁前,未使用Lock()加锁,就会引起一个运行错误。

函数原型

func (m *Mutex) Lock()

Lock方法锁住m,如果m已经加锁,则阻塞直到m解锁。

func (m *Mutex) Unlock()

Unlock方法解锁m,如果m未加锁会导致运行时错误。锁和线程无关,可以由不同的线程加锁和解锁。

一个例子理解互斥锁的作用

package main

import (

"fmt"

"sync"

)

var num = 0

func increment(wg *sync.WaitGroup) {

num = num + 1

wg.Done()

}

func main() {

var w sync.WaitGroup

for i := 0; i < 1000; i++ {

w.Add(1)

//开启协程

go increment(&w)

}

w.Wait()

fmt.Println("num =", num)

}

在上述程序中,调用1000个协程来进行num=num+1操作

运行几次的输出分别为

num = 971

num = 944

num = 959

每次运行都没有达到预期的效果,因为多个并发的协程试图访问 num 的值,这时就会发生竞态条件。

现在我们可以对上述程序加上锁,每次只能由一个线程来操作num的值

package main

import (

"fmt"

"sync"

)

var num = 0

func increment(wg *sync.WaitGroup, m *sync.Mutex) {

//互斥锁

m.Lock() //当有线程进去进行加锁

num = num + 1

m.Unlock() //出来后解锁,其他线程才可以进去

wg.Done()

}

var w sync.WaitGroup

var m sync.Mutex

for i := 0; i < 1000; i++ {

w.Add(1)

go increment(&w, &m)//这里要传引用并不能传值,如果传值,那么每个协程都会得到 Mutex 的一份拷贝,竞态条件还是会发生。

}

w.Wait()

fmt.Println("num =", num)

输出

num = 1000

我们也可以使用缓冲信道来实现互斥锁

func increment2(wg *sync.WaitGroup, b chan bool) {

//自定义互斥锁

b

num = num + 1

wg.Done()

}

func main() {

var w sync.WaitGroup

ch := make(chan bool,1)

for i := 0; i < 1000; i++ {

w.Add(1)

go increment2(&w, ch)

}

w.Wait()

fmt.Println("num =", num)

}

输出

num = 1000

func main() {

wa := sync.WaitGroup{}

var mu sync.Mutex

fmt.Println("加锁0")

mu.Lock()

fmt.Printf("上锁中0\t")

for i := 1; i < 4; i++ {

wa.Add(1)

go func(i int) {

fmt.Printf("加锁%d\t", i)

mu.Lock()

fmt.Printf("上锁中%d\t", i)

time.Sleep(time.Second * 1)

mu.Unlock()

fmt.Printf("解锁%d\t", i)

wa.Done()

}(i)

}

time.Sleep(time.Second * 5)

mu.Unlock()

fmt.Println("\n解锁0")

wa.Wait()

}

输出为

加锁0

上锁中0 加锁2 加锁3 加锁1 上锁中2

解锁0

解锁2 上锁中3 解锁3 上锁中1 解锁1

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值