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要重 ...
随机推荐
- JavaScript获取DOM节点
常用的方法有 document.getElementById("id"); document.getElementsByTagName('tagName'); document.g ...
- vue-devtools 的安装和使用
vue-devtools的安装与使用 一.在github上下载压缩包,github下载地址:https://github.com/vuejs/vue-devtools 二.解压到本地的某盘 三.用你的 ...
- SAP字体调节大小
登陆SAP 之后,菜单下面一行,最右边的那个彩色按钮(SAP GUI),点击“选项”-可视设计-字体设计-固定狂赌字体设计,点击:选择字体 即可.
- [转] python 模块学习 hashlib
转自: http://www.cnblogs.com/BeginMan/p/3328172.html 一.hashlib概述 涉及加密服务:14. Cryptographic Services 其中 ...
- js對象構造
創建對象的3種方式: 1. var a=new Object() a.attributes=“1”: 2. var a={attributes:"1",aa:"2&quo ...
- 使用nexus搭建maven私服教程详解
私服是什么 私服,私有服务器,是公司内部Maven项目经常需要的东东,不总结一下,不足以体现出重视.Nexus是常用的私用Maven服务器,一般是公司内部使用.下载地址是http://www.sona ...
- BZOJ2733[HNOI2012]永无乡——线段树合并+并查集+启发式合并
题目描述 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达 ...
- 【Linux】Screen命令
1.运行screen [root@master2 ~]# screen 2.执行脚本 [root@master2 ~]# sh mgr.sh 命令帮助 更详细的请使用 man screen查看 htt ...
- BZOJ5338 [TJOI2018] Xor 【可持久化Trie树】【dfs序】
题目分析: 很无聊的一道题目.首先区间内单点对应异或值的询问容易想到trie树.由于题目在树上进行,case1将路径分成两段,然后dfs的时候顺便可持久化trie树做询问.case2维护dfs序,对d ...
- BZOJ4870 [六省联考2017] 组合数问题 【快速幂】
题目分析: 构造f[nk][r]表示题目中要求的东西.容易发现递推公式f[nk][r]=f[nk-1][r]+f[nk-1][(r-1)%k].矩阵快速幂可以优化,时间复杂度O(k^3logn). 代 ...