秒懂 Golang 中的 条件变量(sync.Cond)

阅读须知:

本篇文章面向的读者: 已经基本掌握Go中的 协程(goroutine)通道(channel)互斥锁(sync.Mutex)读写锁(sync.RWMutex) 这些知识。如果对这些还不太懂,可以先回去把这几个知识点解决了。

首先理解以下三点再进入正题:

  • Go中的一个协程 可以理解成一个独立的人,多个协程是多个独立的人
  • 多个协程都需要访问的 共享资源(比如共享变量) 可以理解成 多人要用的某种公共社会资源
  • 上锁 其实就是加入到某个共享资源的争抢组中上锁完成 就是从争抢组中被选出,得到了期待的共享资源;解锁 就是退出某个共享资源的争抢组。 

正题:

假如有这样一个现实场景:在一个公园中有一个公共厕所,这个厕所一次只能容纳一个人上厕所,同时这个厕所中有个放卷纸的位置,其一次只能放一卷纸,一卷纸的总长度是 5 米,而每个人上一次厕所需要用掉 1 米的纸。而当一卷纸用完后,公园管理员要负责给厕所加上一卷新纸,以便大家可以继续使用厕所。 那么对于这个单人公共厕所,大家只能排队上厕所,当每个人进到厕所的时候,当然会把厕所门锁好,以便任何人都进不来(包括管理员)。管理员若要进到厕所查看用纸情况并加卷纸,也需要排队(因为插队总是不文明对吧)。

那么怎么用 Golang 去模拟上述场景呢?

首先我们先不用 sync.Cond,看如何实现?那么请看下面这段代码:

package main

import (
	"fmt"
	"time"
	"sync"
)

var 卷纸 int
var m sync.Mutex
var wg sync.WaitGroup

func 上厕所(姓名 string){
	m.Lock()
	defer func(){
		m.Unlock()
		wg.Done()
	}()
	fmt.Printf("%s 进到厕所\t",姓名)
	if 卷纸 >= 1 {  // 进到厕所第一件事是看还有没有纸
		fmt.Printf("正在拉屎中...\n")
		time.Sleep(time.Second)
		卷纸 -= 1
		fmt.Printf("%s 已用完厕所,正在离开\n",姓名)
		return
	} 
	fmt.Printf("发现纸用完了,无奈先离开厕所\n")
}

func 加厕纸(){
	m.Lock()
	defer func(){
		m.Unlock()
		wg.Done()
	}()
	fmt.Printf("公园管理员 进到厕所\t")
	if 卷纸 <= 0 { // 管理员进到厕所是看纸有没有用完
		fmt.Printf("公园管理员 正在加新纸...\n")
		time.Sleep(time.Millisecond*500)
		卷纸 = 5
		fmt.Printf("公园管理员 已加上新厕纸,正在离开\n")
	}else{
		fmt.Printf("发现纸还没用完,先离开厕所\n")
	}
}

func main() {
	卷纸 = 5 // 厕所一开始就准备好了一卷纸,长度5米
	要排队上厕所的人 := [...]string{"老王","小李","老张","小刘","阿明","欣欣","西西","芳芳"}
	for _,谁 :&
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值