golang中的sync
1. Go语言中可以使用sync.WaitGroup来实现并发任务的同步
package main import (
"fmt"
"sync"
) func hello(wg *sync.WaitGroup) {
defer wg.Done()
fmt.Println("hello")
} func main() {
var wg sync.WaitGroup
wg.Add(1)
//go hello(wg) // 注意:wg是一个结构体,传递的时候需要传递指针,此处传递的结构体,导致wg.Wait()一直等待,死锁
go hello(&wg) wg.Wait()
fmt.Println("main over")
}
需要注意sync.WaitGroup是一个结构体,传递的时候要传递指针。
2. sync.Once
在编程的很多场景下我们需要确保某些操作在高并发的场景下只执行一次,例如只加载一次配置文件、只关闭一次通道等。
Go语言中的sync包中提供了一个针对只执行一次场景的解决方案–sync.Once。
sync.Once只有一个Do方法
package main
import (
"fmt"
"log"
"net"
"os"
"sync"
)
var printPid sync.Once
func main() {
listener, err := net.Listen("tcp", "127.0.0.1:18888")
if err != nil {
log.Fatalln(err)
return
}
defer listener.Close()
for {
// 注意:无论for循环遍历多少次,此处的Do方法只会执行一次
printPid.Do(func() {
fmt.Println("当前进程的ID是:", os.Getpid())
})
conn, err := listener.Accept()
if err != nil {
log.Fatalln("监听端口错误", err)
}
log.Println(conn.RemoteAddr(), "链接成功")
//go handleConn(conn) // 开启一个goroutine来处理新到来客户端链接
}
}
sync.Once结构体内部包含了一个互斥锁和布尔值,互斥锁保证布尔值和数据的安全,而布尔值用来记录初始化是否完成,
这样设计就能保证初始化操作的时候是并发安全的,并且初始化操作也不会被执行多次
3. sync.Map
go语言中内置的map不是并发安全的
package main import (
"fmt"
"strconv"
"sync"
) var m = make(map[string]int) func get(key string) int {
return m[key]
}
func set(key string, value int) {
m[key] = value
} func main() {
// 内置的map不是并发安全的
wg := sync.WaitGroup{}
for i := 0; i < 5; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
key := strconv.Itoa(i)
set(key, i)
fmt.Printf("key:%v, value:%v\n", key, get(key))
}(i)
}
wg.Wait()
}
上面的代码开启少量几个goroutine的时候可能没什么问题,当并发多了之后执行上面的代码就会报fatal error: concurrent map writes错误。
像这种场景下就需要为map加锁来保证并发的安全性了,Go语言的sync包中提供了一个开箱即用的并发安全版map–sync.Map。开箱即用表示不用像内置的map一样使用make函数初始化就能直接使用。同时sync.Map内置了诸如Store、Load、LoadOrStore、Delete、Range等操作方法。
package main import (
"fmt"
"strconv"
"sync"
) func main() {
// go语言的sync包提供了开箱即用的并发安全的map-sync.Map,
// 开箱即用表示不用向内置的map一样使用make函数来初始化就能直接使用
var (
m = sync.Map{}
wg sync.WaitGroup
) for i := 0; i < 20; i++ {
wg.Add(1)
go func(i int) {
key := strconv.Itoa(i)
m.Store(key, i) // map赋值
v, _ := m.Load(key)
fmt.Printf("key:%v, value:%v\n", key, v) defer wg.Done()
}(i)
} wg.Wait() }
golang中的sync的更多相关文章
- golang中并发sync和channel
golang中实现并发非常简单,只需在需要并发的函数前面添加关键字"go",但是如何处理go并发机制中不同goroutine之间的同步与通信,golang 中提供了sync包和channel ...
- 【记录一个问题】golang中使用sync.Pool反而造成了负优化
之前有这样的代码:从http收数据后,进行snappy解码: dst := make([]byte, 0, len(httpRequestData)*5) dst, err = snappy.Deco ...
- golang 中 sync包的 WaitGroup
golang 中的 sync 包有一个很有用的功能,就是 WaitGroup 先说说 WaitGroup 的用途:它能够一直等到所有的 goroutine 执行完成,并且阻塞主线程的执行,直到所有的 ...
- golang中sync.RWMutex和sync.Mutex区别
golang中sync包实现了两种锁Mutex (互斥锁)和RWMutex(读写锁),其中RWMutex是基于Mutex实现的,只读锁的实现使用类似引用计数器的功能. type Mutex f ...
- golang 中 sync.Mutex 的实现
mutex 的实现思想 mutex 主要有两个 method: Lock() 和 Unlock() Lock() 可以通过一个 CAS 操作来实现 func (m *Mutex) Lock() { f ...
- Golang中WaitGroup使用的一点坑
Golang中WaitGroup使用的一点坑 Golang 中的 WaitGroup 一直是同步 goroutine 的推荐实践.自己用了两年多也没遇到过什么问题.直到一天午睡后,同事扔过来一段奇怪的 ...
- golang中Context的使用场景
golang中Context的使用场景 context在Go1.7之后就进入标准库中了.它主要的用处如果用一句话来说,是在于控制goroutine的生命周期.当一个计算任务被goroutine承接了之 ...
- golang中锁mutex的实现
golang中的锁是通过CAS原子操作实现的,Mutex结构如下: type Mutex struct { state int32 sema uint ...
- 【协作式原创】查漏补缺之Golang中mutex源码实现(预备知识)
预备知识 CAS机制 1. 是什么 参考附录3 CAS 是项乐观锁技术,当多个线程尝试使用 CAS 同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是 ...
随机推荐
- Linux(Centos)配置vsftp使用账号密码(虚拟用户)登录ftp进行文件上传和修改
安装vsftp yum install vsftpd -y 安装完成之后进入vsftp的配置文件夹 cd /etc/vsftpd/ 文件夹内容如下 [root@VM-0-12-centos vsftp ...
- html5调用摄像头截图
关于html5调用音视频等多媒体硬件的API已经很成熟,不过一直找不到机会把这些硬件转化为实际的应用场景,不过近年来随着iot和AI的浪潮,我觉得软硬结合的时机已经成熟.那我们就提前熟悉下怎么操作这些 ...
- 【LeetCode】794. Valid Tic-Tac-Toe State 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/valid-ti ...
- 1632 B君的连通
B国拥有n个城市,其交通系统呈树状结构,即任意两个城市存在且仅存在一条交通线将其连接.A国是B国的敌国企图秘密发射导弹打击B国的交通线,现假设每条交通线都有50%的概率被炸毁,B国希望知道在被炸毁之后 ...
- codeforce-601A. The Two Routes(最短路)
题意: 给你N个点表示N个站,有汽车和火车,汽车只能走公路,火车只能走铁路. 然后给你M条双向路,代表这两个点之间有铁路连接. 然后告诉你如果两个点之间没有铁路,那么就是公路连接. 问你汽车和火车都到 ...
- 修改gorm支持protobuf
gorm的功能很强大,支持很多很多特性,打算在项目中用上它. 但gorm不支持protobuf,如果idl用的是protobuf,需要对每个message做一个重新定义一个内部的struct,使得可以 ...
- C9软件工程非一线城市面试经验
本人C9软件工程毕业,由于家境一般,不想去一线城市面对天价房价,所以面的都不是互联网大厂. 人生第一面: 2021.11.29 五某汽车 软件工程岗面试 提前3天发了短信,然后拉了一个面试微信群 1. ...
- 人脸识别中的重要环节-对齐之3D变换-Java版(文末附开源地址)
一.人脸对齐基本概念 人脸对齐通过人脸关键点检测得到人脸的关键点坐标,然后根据人脸的关键点坐标调整人脸的角度,使人脸对齐,由于输入图像的尺寸是大小不一的,人脸区域大小也不相同,角度不一样,所以要通过坐 ...
- Java Web程序设计笔记 • 【第2章 JSP基础】
全部章节 >>>> 本章目录 2.1 JSP 简介 2.1.1 JSP 概述 2.1.2 开发第一个 JSP 页面 2.1.3 JSP 处理流程 2.1.4 实践练习 2. ...
- Android开发布局 案例二
实践案例: XML <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:an ...