Golang sync
Go1.9.2 sync库里包含下面几类:Mutex/RWMutex/Cond/WaitGroup/Once/Map/Pool
1.Mutex:互斥锁,等同于linux下的pthread_mutex_t
//多个线程同时运行,获得Mutex锁者线程优先执行,其余线程阻塞等待
func testMutex() {
mutex := sync.Mutex{};
for i := ; i < ; i++ {
go func(idx int) {
mutex.Lock();
defer mutex.Unlock();
fmt.Println("idx :=", idx);
time.Sleep(time.Second);
}(i)
} time.Sleep( * time.Second);
fmt.Println("Func finish.");
}
2.RWMutex:读写锁,等同于linux下的pthread_rwlock_t
//写请求在读锁和写锁时都必须阻塞等待,读请求只在写锁时阻塞等待
func testRWMutex() {
rwMutex := sync.RWMutex{};
for i := ; i < ; i++ {
go func(idx int) {
rwMutex.RLock();
defer rwMutex.RUnlock();
fmt.Println("Read Mutex :",idx);
}(i); go func(idx int) {
rwMutex.Lock();
defer rwMutex.Unlock();
fmt.Println("Write Mutex :",idx);
time.Sleep(time.Second);
}(i);
} time.Sleep( * time.Second);
fmt.Println("Func finish.");
}
3.Cond:条件变量,等同于linux下的pthread_cond_t
func testCond() {
cond := sync.NewCond(&sync.Mutex{});
cond.L.Lock(); //①上锁
defer cond.L.Unlock();
go func() {
fmt.Println("go wait lock.");
cond.L.Lock(); //②等Wait解锁
defer cond.L.Unlock(); //⑤解锁后触发Wait
defer fmt.Println("go unlock.");
fmt.Println("go locked.");
cond.Signal(); //④触发Wait等待解锁
}()
time.Sleep(time.Second);
fmt.Println("start wait.");
for {
cond.Wait(); //③可以理解为立刻解锁并触发一个阻塞线程(如果没有阻塞线程则不触发)后立刻再上锁等待Signal信号
fmt.Println("wait finish.");
break;
}
time.Sleep(time.Second);
fmt.Println("Func finish.");
}
4.WaitGroup:组等待
//Add 增加等待计数;Done减少等待计数;当计数为0时触发Wait;
func testWaitGroup() {
waitGroup := sync.WaitGroup{};
for i := ; i < ; i++ {
waitGroup.Add(); go func(idx int) {
time.Sleep(time.Second);
fmt.Println("go : ", idx);
waitGroup.Done();
}(i)
} for{
fmt.Println("start wait.");
waitGroup.Wait();
fmt.Println("wait finish.");
break;
} time.Sleep(time.Second);
fmt.Println("Func finish.");
}
5.Once:只执行一次
//只执行一次以后不再触发
func testOnce() {
once := sync.Once{};
for i := ; i < ; i++ {
go func(idx int) {
once.Do(func() {
fmt.Println("Do once : ", idx); //这里只执行一次
}) fmt.Println("go : ", idx);
}(i)
} time.Sleep( * time.Second);
fmt.Println("Func finish.");
}
6.Map:线程安全map
func testMap() {
syncMap := sync.Map{};
for i := ; i < ; i++ {
go func(idx int) {
//如果没有则保存起来
_, ok := syncMap.LoadOrStore(idx, " StrVal = "+strconv.FormatInt(int64(idx), ));
if !ok {
fmt.Println("Store idx = ",idx);
}
}(i)
go func(idx int) {
val, ok := syncMap.Load(idx);
if ok {
fmt.Println("Load success idx = ", idx, val);
} else {
fmt.Println("Load fail idx = ", idx)
}
}(i)
}
time.Sleep( * time.Second);
fmt.Println("Func finish.");
}
7.Pool:线程安全对象池
func testPool() {
p := &sync.Pool{
New: func() interface{} {
return -;
},
}
for i := ; i < ; i++ {
go func(idx int) {
p.Put(idx);
}(i)
}
//取出来的对象是无序的
for i := ; i < ; i++ {
go func() {
val := p.Get();
fmt.Println("Get val = ", val);
}()
}
time.Sleep( * time.Second);
fmt.Println("Func finish.");
}
使用Pool一定要注意一下问题:
1.用途仅仅是增加对象重用的几率,减少gc的负担,而开销方面也不是很便宜的。
2.GC会将Pool清理掉。
3.Get不能保证将Put进去的全部取出来!如下例子:
func testPoolPutGet(){
myPool := &sync.Pool{
New: func() interface{} {
return ;
},
}
myPool.Put() //放入1
myPool.Put() //放入2
time.Sleep(time.Second)
p1 := myPool.Get().(int)
fmt.Println(p1) // 获得2
p2 := myPool.Get().(int)
fmt.Println(p2) // 获得0,而不是1!
}
4.关于Pool的实现原理,可以参考《go语言的官方包sync.Pool的实现原理和适用场景》
以上。
Golang sync的更多相关文章
- Golang Sync.WaitGroup 使用及原理
Golang Sync.WaitGroup 使用及原理 使用 func main() { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.A ...
- golang sync/atomic
刚刚学习golang原子操作处理的时候发现github上面一个比较不错的golang学习项目 附上链接:https://github.com/polaris1119/The-Golang-Standa ...
- Golang:sync.Map
由于map在gorountine 上不是安全的,所以在大量并发读写的时候,会出现错误. 在1.9版的时候golang推出了sync.Map. sync.Map 通过阅读源码我们发现sync.Map是通 ...
- golang sync包
sync 在golang 文档上,golang不希望通过共享内存来进行进程间的协同操作,而是通过channel的方式来进行,当然,golang也提供了共享内存,锁等机制进行协同操作的包: 互斥锁: M ...
- golang sync.noCopy 类型 —— 初探 copylocks 与 empty struct
问题引入 学习golang(v1.16)的 WaitGroup 代码时,看到了一处奇怪的用法,见下方类型定义: type WaitGroup struct { noCopy noCopy ... } ...
- golang sync.Cond条件变量的使用
cond.Wait()的操作实际上是对与cond绑定的锁先进行解锁,在等待通知:接收到通知后,会尝试加锁,加锁成功则唤醒否则继续等待通知: cond.Waite()前必须对关连锁加锁,否则panic ...
- golang sync.Pool包的使用和一些注意地方
package main; import ( "sync" "fmt" "net" "runtime" ) //sync ...
- golang sync.Cond 类
众所周知,go语言在多线程方面的支持是十分完备的.在go语言sync包中提供了一个Cond类,这个类用于goroutine之间进行协作. 这个类并不复杂,只有三个函数,Broadcast() , Si ...
- golang sync.RWMutex
sync.RWMutex package main import ( "fmt" "runtime" "sync" ) func click ...
随机推荐
- Python 使用 face_recognition 人脸识别
Python 使用 face_recognition 人脸识别 官方说明:https://face-recognition.readthedocs.io/en/latest/readme.html 人 ...
- Linux 命令梳理
Linux 命令梳理 待梳理命令 nohup 用户管理 useradd 新建用户 sudo useradd {user name} -s /bin/bash -d /data/{user name} ...
- 【python35.1--EasyGui界面】
一.什么是EasyGUI EasyGUI是python中一个非常简单的GUI编程模块,不同于其他的GUI生成器,它不是事件驱动的,相反,所有的GUI交互都是通过简地函数调用就可以实现(意思是:函数调用 ...
- centos 查看USB接口的版本
# lsusbBus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hubBus 002 Device 001: ID 1d6b:000 ...
- How to Install Apache Tomcat 8.5 on CentOS 7.3
How to Install Apache Tomcat 8.5 on CentOS 7.3 From: https://www.howtoforge.com/tutorial/how-to-inst ...
- Centos 安装R
1 下载R源代码 原码下载地址https://cloud.r-project.org/https://cloud.r-project.org/src/base/R-3/R-3.4.2.tar.gz 2 ...
- P3232 [HNOI2013]游走
吐槽 傻了傻了,对着题解改了好长时间最后发现是自己忘了调用高斯消元了... 思路 期望题,分配编号,显然编号大的分给贡献次数小的,所以需要知道每个边被经过次数的期望 然后边被经过的次数的期望就是连接的 ...
- Shiro学习笔记(二)
首先还是先搭建工程运行环境 依旧搭建的是Maven工程,如果不是Maven 也可以去网上找jar包然后导入 (我使用Maven主要是找依赖配置文件就行,我自己导jar包的时候就是很容易报错) 还是先 ...
- Bytom猜谜合约使用指南
准备工作: 1.安装全节点钱包V1.0.5以上并同步完成: 2.已经发行一种资产,发行资产的方法具体见文章<如何在Bytom上发布资产?> 3.准备好一些BTM作为手续费: 设置谜语(锁定 ...
- Redis架构设计
高可用Redis服务架构分析与搭建 各种web开发业务中最为常用的key-value数据库了 应用: 在业务中用其存储用户登陆态(Session存储),加速一些热数据的查询(相比较mysql而言,速度 ...