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的更多相关文章

  1. Golang Sync.WaitGroup 使用及原理

    Golang Sync.WaitGroup 使用及原理 使用 func main() { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.A ...

  2. golang sync/atomic

    刚刚学习golang原子操作处理的时候发现github上面一个比较不错的golang学习项目 附上链接:https://github.com/polaris1119/The-Golang-Standa ...

  3. Golang:sync.Map

    由于map在gorountine 上不是安全的,所以在大量并发读写的时候,会出现错误. 在1.9版的时候golang推出了sync.Map. sync.Map 通过阅读源码我们发现sync.Map是通 ...

  4. golang sync包

    sync 在golang 文档上,golang不希望通过共享内存来进行进程间的协同操作,而是通过channel的方式来进行,当然,golang也提供了共享内存,锁等机制进行协同操作的包: 互斥锁: M ...

  5. golang sync.noCopy 类型 —— 初探 copylocks 与 empty struct

    问题引入 学习golang(v1.16)的 WaitGroup 代码时,看到了一处奇怪的用法,见下方类型定义: type WaitGroup struct { noCopy noCopy ... } ...

  6. golang sync.Cond条件变量的使用

    cond.Wait()的操作实际上是对与cond绑定的锁先进行解锁,在等待通知:接收到通知后,会尝试加锁,加锁成功则唤醒否则继续等待通知: cond.Waite()前必须对关连锁加锁,否则panic ...

  7. golang sync.Pool包的使用和一些注意地方

    package main; import ( "sync" "fmt" "net" "runtime" ) //sync ...

  8. golang sync.Cond 类

    众所周知,go语言在多线程方面的支持是十分完备的.在go语言sync包中提供了一个Cond类,这个类用于goroutine之间进行协作. 这个类并不复杂,只有三个函数,Broadcast() , Si ...

  9. golang sync.RWMutex

    sync.RWMutex package main import ( "fmt" "runtime" "sync" ) func click ...

随机推荐

  1. HTML5<input>标签

    在表单中最为核心的就是<input>标签,使用<input>标签可以在表单中定义文本输入框.单选按钮.复选框.重置按钮等,其基本语法格式如下: <input type=& ...

  2. TCP之 TIME_WAIT和CLOSE_WAIT 状态 的原因分析和处理

    转自:http://blog.csdn.net/shootyou/article/details/6622226 昨天解决了一个HttpClient调用错误导致的服务器异常,具体过程如下: http: ...

  3. android 导出apk

    一个困扰了几个月的问题在今天得以解决,运动益智可能有点过,能让一个人思路清晰倒是真! 问题描述:本地调试运行及不加密导出apk运行正常,当加密生成apk安装后,从接口返回的数据总是空.尝试过各种配置, ...

  4. 复选框批量删除操作-jquery方式

    1.首先在页面添加一个批量删除的按钮:<li class="btns"><input id="deleteSubmit" class=&quo ...

  5. JS深拷贝/深克隆(面试用)

    晒下我的比较浅显的深拷贝,没有考虑原型和循环引用,可以拷贝一些js原生类型,用于面试用. function deepClone(obj){ if(Object.prototype.toString.c ...

  6. 盒子总结,文本属性操作,reset操作,高级选择器,高级选择器优先级,边界圆角(了解),a标签的四大伪类,背景图片操作,背景图片之精灵图

    盒子总结 ''' block: 设置宽高 1.没有设置宽,宽自适应父级的宽(子级的border+padding+width=父级的width) 2.没有设置高,高由内容撑开 设置了宽高 一定采用设置的 ...

  7. topcoder srm 335 div1

    problem1 link 直接模拟即可. import java.util.*; import java.math.*; import static java.lang.Math.*; public ...

  8. ODAC(V9.5.15) 学习笔记(九)TOraSQLMonitor

    名称 类型 说明 Active Boolean 激活SQL跟踪 DBMonitorOptions 将跟踪信息发送到dbMonitor工具软件的选择项 Host IP地址 Port 端口号 Reconn ...

  9. Print a file's last modified date in Bash

    date -r <filename> #!/usr/bin/env bash for i in /var/log/*.out; do stat -f "%Sm" -t ...

  10. C#数字前面如何补0

    PadLeft()函数:向左补齐PadRight()函数:向右补齐 class Program { static void Main(string[] args) { ; Console.WriteL ...