golang锁
golang锁包:https://studygolang.com/pkgdoc
sync.Mutex是一个互斥锁
var lock sync.Mutex
加锁段在中
lock.lock()
lock.unlock()
sync.RWMutex为读写锁。使用方法同互斥锁
package main import (
"fmt"
) func main() {
var a = 1 go func(num *int) {
for n := 0; n < 1000; n++ {
*num++
}
}(&a) go func(num1 *int) {
for i := 0; i < 1000; i++ {
*num1++
}
}(&a) fmt.Println(a)
}
发现执行结果输出为1,原因为主进程在创建完子线程后就结束了。子线程还未执行。也就没有对变量a进程运算
使用sync.WaitGroup等待子线程结束后退出。
package main import (
"fmt"
"sync"
) func main() {
var a int
var wg sync.WaitGroup
wg.Add(2)
go func(num *int) {
for n := 0; n < 100000; n++ {
*num++
}
wg.Done()
}(&a) go func(num1 *int) {
for i := 0; i < 100000; i++ {
*num1++ }
wg.Done()
}(&a)
wg.Wait()
fmt.Println(a)
}
在运行多次后发现并不等于200000,而且每次都不同,原因为线程1在操作a变量时变量为0,运算的1,在运算过程中,线程b也读取a变量此时a还为1,也就造就了运算结果不一致问题。
此时就需要使用锁,sync.Mutex
package main import (
"fmt"
"sync"
) func main() {
var a int
var wg sync.WaitGroup
var lock sync.Mutex
wg.Add(2)
go func(num *int) {
for n := 0; n < 100000; n++ {
lock.Lock()
*num++
lock.Unlock()
}
wg.Done()
}(&a) go func(num1 *int) {
for i := 0; i < 100000; i++ {
lock.Lock()
*num1++
lock.Unlock()
}
wg.Done()
}(&a)
wg.Wait()
fmt.Println(a)
}
执行多次后结果都是唯一的。
数据竞争
func RWlock() {
var a int go func(num *int) {
for n := 0; n < 100000; n++ {
*num++
}
}(&a)
fmt.Println("------", a)
} func main() {
RWlock()
}
编译后执行,提示wirte 线程goroutine 6 与读进程 goroutine main有数据冲突
C:\Users\LC>C:\Users\LC\lock2.exe
------ 0
==================
WARNING: DATA RACE
Write at 0x00c000058058 by goroutine 6:
main.RWlock.func1()
D:/go_work/src/lock/lock2/lock1.go:14 +0x72 Previous read at 0x00c000058058 by main goroutine:
main.RWlock()
D:/go_work/src/lock/lock2/lock1.go:19 +0xd1
main.main()
D:/go_work/src/lock/lock2/lock1.go:23 +0x36 Goroutine 6 (running) created at:
main.RWlock()
D:/go_work/src/lock/lock2/lock1.go:11 +0xc3
main.main()
D:/go_work/src/lock/lock2/lock1.go:23 +0x36
==================
Found 1 data race(s)
在读的地方也加上锁后
lock.Lock()
fmt.Println("------", a)
lock.Unlock()
C:\Users\LC>go build -race lock\lock2 C:\Users\LC>C:\Users\LC\lock2.exe
------ 0
读写锁
读只对共享资源进行读操作,写只对共享资源进行写操作,使用场景,在读多写少时,加互斥锁性能较低,第一个读进行操作时,第二个读进程在等待,他们之间互斥。此时加上读写锁后,第一个线程加上读锁时,后面的资源都可以进行操作。
package main import (
"fmt"
"sync"
"sync/atomic"
"time"
) func rwLock() {
var counts uint32
var lock sync.Mutex
// var lock sync.RWMutex
var num int
for n := 0; n < 3; n++ { //创建3个写线程
go func(number *int) {
lock.Lock()
*number++
time.Sleep(10 * time.Millisecond)
lock.Unlock()
}(&num)
}
for n := 0; n < 100; n++ { //创建100个读线程
go func(number *int) {
for { //每个线程死循环无限读,
// lock.RLock()
lock.Lock()
// fmt.Println(*number)
time.Sleep(time.Millisecond * 3)
lock.Unlock()
// lock.RUnlock()
atomic.AddUint32(&counts, 1) //记录读的次数
}
}(&num)
} time.Sleep(time.Second * 3) //主进程总共执行时间3秒,即3秒内互斥锁和读写锁在读方面可执行多少次
fmt.Println(atomic.LoadUint32(&counts)) //获取读的总次数
} func main() {
rwLock()
}
将读写锁改为互斥锁后,本次测试的次数相差很多
golang锁的更多相关文章
- golang锁记
golang中有两个锁实现 atomic的CAS实现锁 首先是inter cpu,熟悉汇编的人都知道,inter指令集有个lock,如果某个指令集前面加个lock,那么在多核状态下,某个核执行到这个前 ...
- 详解golang net之netpoll
golang版本1.12.9:操作系统:readhat 7.4 golang的底层使用epoll来实现IO复用.netPoll通过pollDesc结构体将文件描述符与底层进行了绑定.netpoll实现 ...
- golang 互斥锁和读写锁
golang 互斥锁和读写锁 golang中sync包实现了两种锁Mutex(互斥锁)和RWMutex(读写锁),其中RWMutex是基于Mutex实现的,只读锁的实现使用类似引用计数器的功能. ty ...
- 使用Golang利用ectd实现一个分布式锁
http://blog.codeg.cn/post/blog/2016-02-24-distrubute-lock-over-etcd/ By zieckey · 2016年02月24日 · 1205 ...
- Golang 读写锁RWMutex 互斥锁Mutex 源码详解
前言 Golang中有两种类型的锁,Mutex (互斥锁)和RWMutex(读写锁)对于这两种锁的使用这里就不多说了,本文主要侧重于从源码的角度分析这两种锁的具体实现. 引子问题 我一般喜欢带着问题去 ...
- golang 并发锁的陷阱
错误代码示例 package main import ( "sync" "strconv" "fmt" ) type Node struct ...
- Golang 入门系列(十六)锁的使用场景主要涉及到哪些?读写锁为什么会比普通锁快
前面已经讲过很多Golang系列知识,感兴趣的可以看看以前的文章,https://www.cnblogs.com/zhangweizhong/category/1275863.html, 接下来要说的 ...
- golang中锁mutex的实现
golang中的锁是通过CAS原子操作实现的,Mutex结构如下: type Mutex struct { state int32 sema uint ...
- 一道并发和锁的golang面试题
今天面试golang碰到了一道考并发和锁的题目,没有完成,所以把它记录下来,仅为以后复习. 场景:在一个高并发的web服务器中,要限制IP的频繁访问.现模拟100个IP同时并发访问服务器,每个IP要重 ...
随机推荐
- PAT L3-008 喊山
https://pintia.cn/problem-sets/994805046380707840/problems/994805050709229568 喊山,是人双手围在嘴边成喇叭状,对着远方高山 ...
- PAT 1083 是否存在相等的差
https://pintia.cn/problem-sets/994805260223102976/problems/994805260780945408 给定 N 张卡片,正面分别写上 1.2.…… ...
- 使用docker-compose 大杀器来部署服务
使用docker-compose 大杀器来部署服务 上 我们都听过或者用过 docker,然而使用方式却是仅仅用手动的方式,这样去操作 docker 还是很原始. 好吧,可能在小白的眼中噼里啪啦的对着 ...
- [转帖]Tensor是神马?为什么还会Flow?
Tensor是神马?为什么还会Flow? 互联网爱好者 百家号17-05-2310:03 大数据文摘作品,转载要求见文末 编译 | 邵胖胖,江凡,笪洁琼,Aileen 也许你已经下载了TensorFl ...
- Jquery ajax load(),get(),post()
//load()用来加载html文档中的代码片段,添加到指定元素内部 //如果只加部分选定的元素可以.load("url 选择器") <!DOCTYPE html>&l ...
- Axure8.0从入门到精通
1. 新建工程 菜单->File->New 2. 添加组件并编辑组件 选中左侧Libary可选择Default/Flow/Icons,找到相应的组件并移动到工作区:并在右侧选中相应的组件属 ...
- 跪求delphi 中的bitbutton 中的bmp图标
C:\Program Files (x86)\Embarcadero\RAD Studio\11.0\Images\GlyFX
- char类型的数值转换
在视频教程中,你已经认识到了数字类型之间.字符串和其他类型之间的转换.而某些时候,我们还需要将char类型转换为int类型,或者把int类型转换为char类型. 这篇文章,将介绍在代码中虽然不太常用, ...
- BZOJ1901Zju2112 Dynamic Rankings——树状数组套主席树
题目描述 给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1 ],a[i+2]……a[j]中第k小的数是多少(1≤k ...
- BZOJ2001 HNOI2010城市建设(线段树分治+LCT)
一个很显然的思路是把边按时间段拆开线段树分治一下,用lct维护MST.理论上复杂度是O((M+Q)logNlogQ),实际常数爆炸T成狗.正解写不动了. #include<iostream> ...