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. Golang两种方法实现MD5加密

    package main import ( "crypto/md5" "fmt" "io" ) func main() { str := & ...

  2. hihocoder [Offer收割]编程练习赛14

    A.小Hi和小Ho的礼物 谜之第1题,明明是第1题AC率比C还要低.题目是求在n个不同重量袋子选4袋,2袋给A,2袋给B,使2人获得重量相同,求问方案数. 我也是一脸懵b...o(n2)暴力枚举发现把 ...

  3. Python 操作 mysql数据库的一个小小的基础案例,小白新手,以备后用~~

    model.py 中的代码 # Create your models here. # 书和作者一对多 class Author(models.Model): name = models.CharFie ...

  4. linux 查看和修改文件时间

    参考:https://www.cnblogs.com/chjbbs/p/6437879.html?utm_source=itdadao&utm_medium=referral . 同时修改文件 ...

  5. topcoder srm 689 div1 -3

    1.给出一个$2*n$的矩阵,只包含小写字母.重新排列各个元素使得任意两个相邻的元素不相同? 思路:按照每种字符的数量降序排序,然后从多到少依次放每一种.放的时候一上一下交错放置. #include ...

  6. Vue学习【第一篇】:Vue初识与指令

    什么是Vue 什么是Vue Vue.js是一个渐进式JavaScript框架它是构建用户界面的JavaScript框架(让它自动生成js,css,html等) 渐进式:vue从小到控制页面中的一个变量 ...

  7. debian下如何源码安装tmux

    一.源码安装ncurses库 1.1 获取源码 wget https://invisible-island.net/datafiles/release/ncurses.tar.gz tar xvf n ...

  8. RHEL7和RHEL6即时设置、开启和开机、永久开启服务的方法、原理(例子:端口与Nginx冲突的Apache httpd服务的关闭)

    1.RHEL7 说明:启用服务就是在当前 runlevel 的配置文件目录/etc/systemd/system/multi-user.target.wants/里,建立/usr/lib/system ...

  9. Css下拉菜单设置

    <style type="text/css"> *{margin:0px;padding:0px;}设置所有标签属性<初始化页面属性> #nav{backg ...

  10. Twitter开发2

    There are different API families The standard (free) Twitter APIs consist of REST APIs and Streaming ...