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 ...
随机推荐
- bzoj4720 / P1850 换教室(Floyd+期望dp)
P1850 换教室 先用Floyd把最短路处理一遍,接下来就是重头戏了 用 f [ i ][ j ][ 0/1 ] 表示在第 i 个时间段,发出了 j 次申请(注意不一定成功),并且在这个时间段是否( ...
- Linux UinxODBC安装与配置
Linux UinxODBC安装与配置 一.简介 ODBC是Open Database Connect 即开发数据库互连的简称,它是一个用于访问数据库的统一界面标准.ODBC引入一个公共接口以解决不同 ...
- ssh-keygen 命令
功能 生成.管理和转换认证密钥,包括 RSA 和 DSA 两种密钥,密钥类型可以用 -t 选项指定.如果没有指定则默认生成用于SSH-2的RSA密钥,系统管理员还可以用它产生主机密钥. 通常,这个程序 ...
- XXX银行项目部署
XXX银行项目部署 一.下载项目代码 1.使用git工具下载代码 代码路径:推荐代码下载到桌面 git clone http://sunyard_姓名拼音@bitbucket.devops.hfdev ...
- python简说(十八)导入模块
1.import xx import 一个模块的实质就是把这个python文件从头到尾执行一遍 2.import模块的查找模块的顺序 1).从当前目录下找 2).sys.path python的安装目 ...
- 你不知道的JavaScript(1)LHS查询和RHS查询
打算把<你不知道的JavaScript>中的知识点整理下,写点自己的心得,同时也敦促自己看书. 先做个整体的介绍,最后会再给个综合的例子. RHS 查询与简单地查找某个变量的值别无二致,而 ...
- python --- 20 约束 异常处理 MD5 日志
一.类的约束 1.抛出异常 NotImplementedError 2.抽象方法 含有抽象方法的类是抽象类 抽象类中的方法全是抽象方法的是接口 抽象类不能创建对象 二.异常处理 处理完后代码可继 ...
- Class DesiredCapabilities
public class DesiredCapabilities extends java.lang.Object implements java.io.Serializable, Capabilit ...
- uniGUI试用笔记(七)
uniGUI的文件下载由于TUniSession的存在而变得非常简单,最典型的一个例子就是将列表中的所有数据导出到Excel中.服务器上采用TMS FlexCel控件,先将数据集中的记录导入到Exce ...
- 【Hadoop 分布式部署 一 :分布式部署准备虚拟机 】
一.将IP配置为静态 按照 下面的操作将IP配置为静态IP 这个静态的IP地址 是你自己设置的,只要符合虚拟机的IP段就可以.最后点击 Apply 需要root密码 将网络断开 (在网络图标左键 ...