golang中的互斥锁
简介
每个资源都对应一个可称为"互斥锁"的标记,这个标记用来保证在任意时刻,只有一个协程(线程)访问该资源.其他的协程只能等待
由标准库sync中的Mutex结构体类型表示.
sync.Mutex
类型只有两个公开的指针方法,Lock和Unlock.
Lock锁定当前的共享资源,Unlock进行解锁
使用互斥锁时,一定要注意:对资源操作完成后,一定要解锁,否则出现流程执行异常,死锁问题.通常借助defer.锁定后,立即使用defer语句保证互斥锁及时解锁
var mutex sync.Mutex //定义互斥锁变量func write() {muter.Lock()defer muter.Unlock()
}
使用
//新创建为0.表示没有加锁,锁只有1把
var mutex sync.Mutexfunc printer(str string) {mutex.Lock()for _, ch := range str {fmt.Println(string(ch))time.Sleep(300 * time.Millisecond)}//共享数据访问结束mutex.Unlock()
}func person1() {printer("11")
}func person2() {printer("222")
}func main() {//先,因为他先获得锁go person1()//后go person2()for {;}
}
不是强制性的
互斥锁的使用是主动控制互斥锁,即一个愿打一个愿挨。比如即使一个routine里用了Lock(),但在另一个routine可以不理会这个锁就能访问这个struct,只需要不调用Lock()就行。例子如下
package mainimport ("fmt""sync""time"
)type SafeCounter struct {v map[string]intmux sync.Mutex
}func (c *SafeCounter) Inc(key string) {c.mux.Lock()time.Sleep(3 * time.Second)c.v[key]++c.mux.Unlock()
}func main() {c := SafeCounter{v: make(map[string]int)}go c.Inc("somekey")time.Sleep(1 * time.Second)c.v["somekey"]++fmt.Println(c.v["somekey"])time.Sleep(3 * time.Second)fmt.Println(c.v["somekey"])
}
输出
1
2
c.v["somekey"]++
之前,是已经锁了,本应该等2-3秒,才能输出,但是从程序开始运行,只过了1秒就输出了,说明Lock只是一种人为的互斥,是一种协议,并不是强制。
已经锁定的Mutex与特定的goroutine无关联
已经锁定的Mutex并不与特定的goroutine相关联,这样可以利用一个goroutine对其加锁,再利用其他goroutine对其解锁,例子如下
package mainimport ("fmt""sync""time"
)type MyStruct struct {v intmux sync.Mutex
}func (s *MyStruct) Lock() {s.mux.Lock()
}func (s *MyStruct) Unlock() {s.mux.Unlock()
}func main() {s := MyStruct{v: 0}s.v = 1fmt.Printf("%+v\n", s)go s.Lock()time.Sleep(1 * time.Second)fmt.Printf("%+v\n", s)go s.Unlock()time.Sleep(1 * time.Second)fmt.Printf("%+v\n", s)
}
输出
{v:1 mux:{state:0 sema:0}}
{v:1 mux:{state:1 sema:0}}
{v:1 mux:{state:0 sema:0}}
可以看出,可以一个routine里锁定,另一个routine里解锁。因为锁只和具体变量关联,和routine无关,只要这个变量是共享的,比如通过指针传递,或者全局变量都可以。
虽然互斥锁可以被直接的在多个Goroutine之间共享,但是我们还是强烈建议把对同一个互斥锁的成对的锁定和解锁操作放在同一个层次的代码块中。例如,在同一个函数或方法中对某个互斥锁的进行锁定和解锁。
golang中的互斥锁相关推荐
- Java中的互斥锁介绍
前言 互斥锁是一种广泛应用于多线程编程中的并发控制机制.在Java中,互斥锁有很多不同的实现方式,在本文中我们将介绍Java中常见的几种互斥锁实现方式,并讲解它们的用法.原理和代码案例. sync ...
- 在ATS插件中使用互斥锁
有时候因为业务需要,对某些非线程函数,比如mktime,需要使用互斥锁,可以参照example/blacklist-1或者channel_stats里面的用法 首先插件顶部声明 static TSMu ...
- Python多任务(4.多线程--Python中的互斥锁和死锁)
互斥锁 1.互斥锁的概念 2.互斥锁的使用 3.使用互斥锁完成2个线程对同一全局变量各加100万次的操作,而不会出现问题 死锁 死锁的概念 避如何免死锁: 出现死锁的例子 互斥锁 1.互斥锁的概念 互 ...
- python中的互斥锁
如果没有控制多个线程对同一资源的访问,对数据造成破坏,使得线程运行的结果不可预期.这种现象称为"线程不安全". 线程同步解决问题: 系统调用t1,然后获取到num的值为0,此时上一 ...
- Golang——死锁、互斥锁、读写锁的实现
死锁: 什么是锁呢?就是某个协程(线程)在访问某个资源时先锁住,防止其它协程的访问,等访问完毕解锁后其他协程再来加锁进行访问.这和我们生活中加锁使用公共资源相似,例如:公共卫生间. 死锁是指两个或两个 ...
- 操作系统中的互斥锁与条件变量
转自https://www.douban.com/note/226974753/ 与互斥锁不同,条件变量是用来等待而不是用来上锁的.条件变量用来自动阻塞一个线程,直到某特殊情况发生为止.通常条件变量和 ...
- golang RWMutex读写互斥锁源码分析
针对Golang 1.9的sync.RWMutex进行分析,与Golang 1.10基本一样除了将panic改为了throw之外其他的都一样. RWMutex是读写互斥锁.锁可以由任意数量的读取器或单 ...
- 内核中的互斥锁的使用
在内核中结构体struct mutex的定义 // include/linux/mutex.h/** Simple, straightforward mutexes with strict seman ...
- golang sync.Mutex 互斥锁 使用实例
实例: var mutex sync.Mutex //互斥锁 func printer(str string){mutex.Lock() //加锁defer mutex.Unlock() //解锁fo ...
最新文章
- PS Material 漫谈 六: Material Availability Check
- HDU 6833 A Very Easy Math Problem
- python生成c语言代码_Python爬取C语言中文网教程生成PDF
- mysql ignore 1 lines_MYSQL使用笔记(1)
- win10计算机管理员权限删除,win10需要管理员权限删除文件怎么办?获取管理员权限删除文件夹...
- Markdown快捷键
- 解决azkaban使用腾讯企业邮箱发邮件失败问题
- 关闭windows Defender的自动扫描
- agent常见处理问题的处理
- 善网ESG报告(第十期)
- 计算机主机突然断电有什么影响吗,断电对电脑的伤害大吗?有什么损伤?
- Android:从assets资源目录下安装apk
- python已知两条直角边求斜边,Python实现“已知三角形两个直角边,求斜边”
- 前端如何调用后端接口
- 前端基础(HTML、CSS、JS)
- Unity Bolt插件 基本使用
- CVer最想知道的,简单分析下《2020年度中国计算机视觉人才调研报告》
- 生信笔记 | 探索PubMed数据库文献
- Java、JSP基于Web的师生互动系统的设计与实现
- oracle的时间各式,Oracle9i日期格式几点说明
热门文章
- 【Linux 操作系统】Ubuntu 配置 ftp freemind adb
- JVM 常用参数一览表(转)
- javascript DOM 编程艺术 札记2 平稳退化
- Let Me Count The Ways(Kickstart Round H 2018)
- matlab 文件路径问题
- 修复efi引导的win7
- 网页防止另存为,屏蔽右键,防止复制代码,防止被人frame等网页代码
- 机器人雅可比矩阵的求法_构造法
- 用 TS + Vue 写了一个在 Chrome 中运行 Prettier 格式化的扩展程序
- IE11 统治浏览器市场 Chrome 终超 Firefox