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

ops/2024/12/18 6:07:35/

代码实现

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/ops/142825.html

相关文章

idea无法识别文件,如何把floder文件恢复成model

前景&#xff1a; 昨天&#xff0c;我在之前的A1214模块包下新增了一个demo类&#xff0c;然后又新建了一个A1216模块&#xff0c;写了算法题&#xff0c;后面打算用git提交&#xff0c;发现之前的A1214模块下的demo类和新建的模块源文件都已经被追踪了&#xff0c;都是绿色的&…

用豆包MarsCode IDE,从0到1画出精美数据大屏!

豆包MarsCode IDE 是一个云端 AI IDE 平台&#xff0c;通过内置的 AI 编程助手&#xff0c;开箱即用的开发环境&#xff0c;可以帮助开发者更专注于各类项目的开发。 作为一名前端开发工程师&#xff0c;今天想尝试利用豆包MarsCode IDE&#xff0c;选择 Vue Echarts 创建一个…

在项目中import 语句通常遵循的顺序规范

一般推荐的顺序是&#xff1a; React 相关的核心包第三方库/依赖组件导入工具/常量/类型导入样式文件导入 比如&#xff1a; // 1. React 相关 import { useEffect, useState } from react; import { useLocation } from react-router-dom;// 2. 第三方库 import { Dialog }…

【网络安全】WIFI WPA/WPA2协议:深入解析与实践

WIFI WPA/WPA2协议&#xff1a;深入解析与实践 1. WPA/WPA2 协议 1.1 监听 Wi-Fi 流量 解析 WPA/WPA2 的第一步是监听 Wi-Fi 流量&#xff0c;捕获设备与接入点之间的 4 次握手数据。然而&#xff0c;设备通常不会频繁连接或重新连接&#xff0c;为了加速过程&#xff0c;攻…

中英文网店系统运营风险 跨境电商平台法律与税务处理

欢迎来到今天的电商运营小课堂&#xff01;今天我们探讨跨境电商平台的运营风险&#xff0c;尤其是中英文网店系统的使用&#xff0c;以及如何应对不同地区的法律与税务挑战。首先&#xff0c;我们来看看中英文网店系统的运营风险。很多跨境电商平台需要支持多语言切换&#xf…

Android Studio、JDK、AGP、Gradle、kotlin-gradle-plugin 兼容性问题

文章目录 问题&#xff1a;解决办法&#xff1a;gradle与 java的版本兼容AGP与Gradle的版本兼容kotlin 与 jvm 的版本兼容KGP、Gradle、AGP兼容关系kotlin 与 java 的编译版本配置 问题&#xff1a; 你从githb上clone了一个项目&#xff0c;本地跑的时候&#xff0c;各种报错。…

Day9 神经网络的偏导数基础

多变量函数与神经网络 在神经网络中&#xff0c;我们经常遇到多变量函数。这些函数通常描述了网络的输入、权重、偏置与输出之间的关系。例如&#xff0c;一个简单的神经元输出可以表示为&#xff1a; z f ( w 1 x 1 w 2 x 2 … w n x n b ) z f(w_1x_1 w_2x_2 \ldots…

HCIA-Access V2.5_3_3_1_VLAN路由原理

VLAN的缺点 对于VLAN而言&#xff0c;最大的好处就是隔离了二层广播域&#xff0c; 减少了广播域的范围&#xff0c;但是它也带来了新的问题&#xff0c;不同VLAN下的用户再也无法实现通信&#xff0c;图中V LAN100的主机无法跟VLAN200的主机实现互通。那么如何解决VLAN间的互通…