Go语言的互斥锁Mutex
一、使用方法
Mutext是互斥锁的意思,也叫排他锁,同一时刻一段代码只能被一个线程运行,两个方法Lock(加锁)和Unlock(解锁)
func main() {
var count = 0
var wg sync.WaitGroup
//十个协程数量
n := 10
wg.Add(n)
for i := 0; i < n; i++ {
go func() {
defer wg.Done()
//1万叠加
for j := 0; j < 10000; j++ {
count++
}
}()
}
wg.Wait()
fmt.Println(count)
}
运行结果如下
38532
添加锁
func main() {
var count = 0
var wg sync.WaitGroup
var mu sync.Mutex
//十个协程数量
n := 10
wg.Add(n)
for i := 0; i < n; i++ {
go func() {
defer wg.Done()
//1万叠加
for j := 0; j < 10000; j++ {
mu.Lock()
count++
mu.Unlock()
}
}()
}
wg.Wait()
fmt.Println(count)
}
运行结果如下,可以看到,已经看到结果变成了正确的100000

二、死锁场景
当两个或两个以上的进程在执行过程中,因争夺资源而处理一种互相等待的状态,如果没有外部干涉无法继续下去,这时我们称系统处于死锁或产生了死锁
1.Lock/Unlock不是成对出现
良好的编程习惯应该是让mu.Lock()和 defer mu.Unlock()成对出现,能有效的降低死锁出现的概率,比如忘了Lock或忘了Unlock,代码建议以下面紧凑的方式出现
mu.Lock()
defer mu.Unlock()
2.锁被拷贝使用
package main
import (
"fmt"
"sync"
)
func main() {
var mu sync.Mutex
mu.Lock()
defer mu.Unlock()
copyTest(mu)
}
//这里复制了一个锁,造成了死锁
func copyTest(mu sync.Mutex) {
mu.Lock()
defer mu.Unlock()
fmt.Println("ok")
}
在函数外层已经加了一个Lock,在拷贝的时候又执行了一次Lock,因此这是一个永远不会获得的死锁
3.循环等待
A等待B,B等待C,C等待A,陷入了无限循环(哲学家就餐问题)
package main
import (
"sync"
)
func main() {
var muA, muB sync.Mutex
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
muA.Lock()
defer muA.Unlock()
//A依赖B
muB.Lock()
defer muB.Lock()
}()
go func() {
defer wg.Done()
muB.Lock()
defer muB.Lock()
//B依赖A
muA.Lock()
defer muA.Unlock()
}()
wg.Wait()
}
Go语言的互斥锁Mutex的更多相关文章
- 互斥锁Mutex与信号量Semaphore的区别
转自互斥锁Mutex与信号量Semaphore的区别 多线程编程中,常常会遇到这两个概念:Mutex和Semaphore,两者之间区别如下: 有人做过如下类比: Mutex是一把钥匙,一个人拿了就可进 ...
- 深入理解Solaris内核中互斥锁(mutex)与条件变量(condvar)之协同工作原理
在Solaris上写内核模块总是会用到互斥锁(mutex)与条件变量(condvar), 光阴荏苒日月如梭弹指一挥间,Solaris的大船说沉就要沉了,此刻心情不是太好(Orz).每次被年轻的有才华的 ...
- Linux内核互斥锁--mutex
一.定义: /linux/include/linux/mutex.h 二.作用及访问规则: 互斥锁主要用于实现内核中的互斥访问功能.内核互斥锁是在原子 API 之上实现的,但这对于内核用户是不可见 ...
- 线程锁(互斥锁Mutex)及递归锁
一.线程锁(互斥锁) 在一个程序内,主进程可以启动很多个线程,这些线程都可以访问主进程的内存空间,在Python中虽然有了GIL,同一时间只有一个线程在运行,可是这些线程的调度都归系统,操作系统有自身 ...
- 线程锁(互斥锁Mutex)
线程锁(互斥锁Mutex) 一个进程下可以启动多个线程,多个线程共享父进程的内存空间,也就意味着每个线程可以访问同一份数据,此时,如果2个线程同时要修改同一份数据,会出现什么状况? # -*- cod ...
- Golang 读写锁RWMutex 互斥锁Mutex 源码详解
前言 Golang中有两种类型的锁,Mutex (互斥锁)和RWMutex(读写锁)对于这两种锁的使用这里就不多说了,本文主要侧重于从源码的角度分析这两种锁的具体实现. 引子问题 我一般喜欢带着问题去 ...
- 一文带你剖析LiteOS互斥锁Mutex源代码
摘要:多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的临界资源,只能被独占使用.LiteOS使用互斥锁来避免这种冲突,互斥锁是一种特殊的二值性信号量,用于实现对临界资源的独占 ...
- [Go] golang互斥锁mutex
1.互斥锁用于在代码上创建一个临界区,保证同一时间只有一个goroutine可以执行这个临界区代码2.Lock()和Unlock()定义临界区 package main import ( " ...
- Go基础系列:互斥锁Mutex和读写锁RWMutex用法详述
sync.Mutex Go中使用sync.Mutex类型实现mutex(排他锁.互斥锁).在源代码的sync/mutex.go文件中,有如下定义: // A Mutex is a mutual exc ...
随机推荐
- websocket+sockjs+stompjs详解及实例
最近有项目需求要用到websocket,刚开始以为很简单,但是随着遇到问题,深入了解,才知道websocket并不是想象中的那么简单,这篇文章主要是考虑websocket在客户端的使用. 1.http ...
- Layman ThinkPHP 中 where条件 or,and 同时使用
Eg:('a'=1 and 'b'=2) or ('c'=3 and 'd'=4) and 'e'=5 解决方法 $condition1['a'] = 1; $condition1['b'] = 2; ...
- Java高级特性1_流库_初体验
Java高级特性流库_初体验 面对结果编程 在编程里, 有两种编程方式, 一种是面对过程编程, 一种是面对结果编程. 两者区别如下 面向过程编程 面向过程编程需要编程程序让程序依次执行得到自己想要的结 ...
- sprintf_s() 、sprintf()和printf()区别和用法
转载:https://blog.csdn.net/qq_35608277/article/details/80878802 int sprintf_s(char *buffer,size_t size ...
- apt-get 安装软件时出现:“文件尺寸不符” 问题
报错信息 命中:1 http://packages.deepin.com/deepin panda InRelease 命中:2 http://linux.teamviewer.com/deb sta ...
- Hive理论基础
数仓特征:面向主题,集成,非易失的,时变.数据仓库是在数据库已经大量存在的情况下,为了进一步挖掘数据资源.为了决策需要而产生的,不是所谓的"大型数据库". 数据库与数据仓库的区 ...
- 常见的Mysql十款高可用方案
简介 我们在考虑MySQL数据库的高可用架构时,主要考虑如下几方面: 如果数据库发生了宕机或者意外中断等故障,能尽快恢复数据库的可用性,尽可能的减少停机时间,保证业务不会因为数据库的故障而中断. 用作 ...
- gitlab-配置邮件
一:配置邮件 1. 进入配置文件,通过修改/etc/gitlab/gitlab.rb来设置邮件功能 修改后的文件 1 ## GitLab URL 2 ##! URL on which GitLab ...
- MeteoInfoLab脚本示例:格点数据散点图
绘制格点数据的散点图,用scaterm函数. 脚本程序: f = addfile('D:/Temp/GrADS/model.ctl') ps = f['PS'][0,(10,60),(60,140)] ...
- Verilog基础入门——简单的语句块编写(一)
[题干] [代码] module top_module ( input in, output out ); assign out = ~in; endmodule 简单的实现一个非门