【go每日一题】 channel实现mutex锁

news/2024/12/19 5:11:03/

代码实现

package testimport ("fmt""strconv""testing""time"
)type mutexCh struct { //应该大写,给外部所有包用ch chan int // 私有变量,否则外部操作
}func NewMutexCh() *mutexCh {return &mutexCh{ch: make(chan int, 1)}
}func (mc *mutexCh) TryLock() {mc.ch <- 1
}func (mc *mutexCh) TryUnlock() {select {case <-mc.ch:default:panic("unlock an unlocked lock")}
}
func TestChLock(t *testing.T) {mc := NewMutexCh()m := map[int]string{0: "hello",1: "world",}for i := 0; i < 10; i++ {go func(mc *mutexCh, m map[int]string, num int) {mc.TryLock() //阻塞获取锁m[0] = m[0] + strconv.Itoa(i)mc.TryUnlock()}(mc, m, i)}select {default:<-time.After(time.Second)fmt.Println(m)}}

改进点

实际上应该提供Lock方法(阻塞等待),TryLock(如果被占有就返回False)
参考golang实现mutex的源码(内部实际上通过信号量实现)

// Lock locks m.
// If the lock is already in use, the calling goroutine
// blocks until the mutex is available.
func (m *Mutex) Lock() {// Fast path: grab unlocked mutex.if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) {if race.Enabled {race.Acquire(unsafe.Pointer(m))}return}// Slow path (outlined so that the fast path can be inlined)m.lockSlow()
}// TryLock tries to lock m and reports whether it succeeded.
//
// Note that while correct uses of TryLock do exist, they are rare,
// and use of TryLock is often a sign of a deeper problem
// in a particular use of mutexes.
func (m *Mutex) TryLock() bool {old := m.stateif old&(mutexLocked|mutexStarving) != 0 {return false}// There may be a goroutine waiting for the mutex, but we are// running now and can try to grab the mutex before that// goroutine wakes up.if !atomic.CompareAndSwapInt32(&m.state, old, old|mutexLocked) {return false}if race.Enabled {race.Acquire(unsafe.Pointer(m))}return true
}

使用select模拟tryLock()

type Mutex struct {ch chan struct{}
}// init clock
func NewMutex() *Mutex {mutex := &Mutex{ch: make(chan struct{}, 1),}return mutex
}// get lock
func (m *Mutex) Lock() {m.ch <- struct{}{}
}// return lock
func (m *Mutex) Unlock() {select {case <-m.ch :default:panic("unlock the unlocked mutex")}
}// try get lock
func (m *Mutex) TryLock() bool {select {case m.ch <- struct{}{}:return truedefault:return false}
}func (m *Mutex) LockTimeout(timeout time.Duration) bool {timer := time.NewTimer(timeout)select {case <-timer.C:case m.ch <- struct{}{}:timer.Stop()return true}return false
}func (m Mutex) IsLocked() bool {return len(m.ch) == 1
}

http://www.ppmy.cn/news/1556305.html

相关文章

解决git push出现的报错:Permission denied (publickey)

报错信息 解决办法 依次输入下面的命令即可

VScode:常见问题的原因及其解决方案

报错代码报错原因解决方案npm ERR! code CERT_HAS_EXPIRED证书过期 依次执行以下命令&#xff1a; npm cache clean --force npm config set strict-ssl false 暂无包更新后版本控制文件&#xff08;yarn.lock&#xff09;未更新 yarn.lock删掉 然后再安一遍包(yarn install) …

Vue3 — h()函数

前言&#xff1a; 翻译的官网文档&#xff01;&#xff01;&#xff01; 正文&#xff1a; h()函数用于创建虚拟DOM节点&#xff0c;虚拟DOM是Vue框架中的核心概念&#xff0c;通过它&#xff0c;可以更高效的更新页面内容。 语法&#xff1a; function h(type:string|Comp…

远程控制电脑技术让我们的生活更加简化

在忙碌的现代生活节奏下&#xff0c;远程控制电脑技术已经成为我们生活中不可或缺的一部分。无论是在家办公&#xff0c;还是在旅途中需要紧急处理工作&#xff0c;远程控制电脑都能为我们提供极大的便利。今天&#xff0c;我们就来聊聊远程控制电脑技术是如何简化我们的生活&a…

Jupyter Notebook的安装与使用

Jupyter Notebook 是一个开源的交互式笔记本环境&#xff0c;可用于进行数据分析、可视化、机器学习建模等工作。它支持多种编程语言&#xff0c;包括 Python、R 和 Julia 等&#xff0c;因此非常适合数据科学家和研究人员。 使用 Jupyter Notebook&#xff0c;你可以在一个网页…

【STM32 Modbus编程】-作为从设备读取保持-输入寄存器

作为从设备读取保持-输入寄存器 文章目录 作为从设备读取保持-输入寄存器1、硬件准备与连接1.1 RS485模块介绍1.2 硬件配置与接线1.3 软件准备1.4 STM32基础代码准备2、读取保持寄存器3、读取输入寄存器在本文中,我们将STM32单片作为ModBus的从设备,实现保持寄存器和输入寄存…

Kubernetes 存储方案

Kubernetes 存储方案 在 Kubernetes&#xff08;K8s&#xff09;中&#xff0c;容器是无状态的&#xff0c;意味着它们在启动、停止或重启时不会保留数据。虽然这种设计让容器非常轻量和灵活&#xff0c;但在实际应用中&#xff0c;我们往往需要持久化存储&#xff0c;比如数据…

LeetCode hot100-82

https://leetcode.cn/problems/pascals-triangle/description/?envTypestudy-plan-v2&envIdtop-100-liked 118. 杨辉三角 已解答 简单 相关标签 相关企业 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。在「杨辉三角」中&#xff0c;每个数是它…