Go并发编程--基于channel信号量来实现互斥锁

概述

根据前面的一片文章:《Go并发编程–通过channel来实现信号量原语》我们实现了信号量的基本原语P和V操作,本章介绍如何通过P操作和V操作来实现互斥锁。

实现原理

当我们把channel的容量设置为1时,P和V操作就变成了,lock和unlock操作。为什么呢?我们来看下代码实现:

/* mutexes */
func (s semaphore) Lock() {
    s.P(1)
}

func (s semaphore) Unlock() {
    s.V(1)
}

上篇讲过P和V操作的实现,当channel的容量只有一个,此时P和V的数量变为1时,进行P操作的协程只能有一个,在该协程执行完P操作没有执行V操作时,其他协程只能等待,这样就实现了只能有一个协程访问临界区的功能。

完整代码

package main

import (
    "fmt"
    "os"
    "time"
)

type Empty interface {}
type semaphore chan Empty

// 实现信号量原语
// acquire n resources
func (s semaphore) P(n int) {
    e := new(Empty)
    for i := 0; i < n; i++ {
        s <- e
    }
}

// release n resources
func (s semaphore) V(n int) {
    for i := 0; i < n; i++ {
        <-s
    }
}

// 通过以上原语实现互斥锁
/* mutexes */
func (s semaphore) Lock() {
    s.P(1)
}

func (s semaphore) Unlock() {
    s.V(1)
}

// 工作协程,这里只是打印0-99的整数
func printInt(sem semaphore) {
    sem.Lock()
    for i := 0; i < 100; i++ {
        fmt.Fprintf(os.Stderr, "%d\n", i)
    }
    sem.Unlock()
}

func main()  {
    sem := make(semaphore, 1)

    go printInt(sem)
    go printInt(sem)

    // 等待两个goroutine结束
    time.Sleep(10e9)
    fmt.Fprintf(os.Stderr, "end\n")
}

当channel容量时1是,就只能有一个协程能完成P操作,直到该协程完成了V操作,其他协程才能进行P操作,这样就实现了互斥锁。

总结

通过channel实现的信号量原语,我们实现了互斥锁。通过P和V原语我们还能实现信号量的一些操作,从而更好的控制协程间的通信。如何实现信号量操作,请继续看后面的文章。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值