Go语言中文网 为您找到相关结果 90

golang单例模式

1、定义:单例对象的类必须保证只有一个实例存在,全局有唯一接口访问。 2、分类: 懒汉方式:指全局的单例实例在第一次被使用时构建。 饿汉方式:指全局的单例实例在类装载时构建。 3、实现: (1)懒汉方式 1 type singleton struct{} 2 var ins *singleton 3 func GetIns() *singleton{ 4 if ins == nil { 5 ins = &singleton{} 6 } 7 return ins 8 } 缺点:非线程安全。当正在创建时,有线程来访问此时ins = nil就会再创建,单例类就会有多个实例了。 (2)饿汉方式 1 type singleton struct{} 2 var ins *singleton = &sin...阅读全文

博文 2017-10-22 16:00:00 YYRise

go语言的官方包sync.Pool的实现原理和适用场景

已经使用golang有一段时间,go的协程和gc垃圾回收特性的确会提高程序的开发效率。但是毕竟是一门新语言,如果对于它的机制不了解,用起来可能会蹦出各种潘多拉盒子。今天就讲讲我在项目中用到的sync包的Pool类的使用,以免大家混淆使用。 众所周知,go是自动垃圾回收的(garbage collector),这大大减少了程序编程负担。但gc是一把双刃剑,带来了编程的方便但同时也增加了运行时开销,使用不当甚至会严重影响程序的性能。因此性能要求高的场景不能任意产生太多的垃圾(有gc但又不能完全依赖它挺恶心的),如何解决呢?那就是要重用对象了,我们可以简单的使用一个chan把这些可重用的对象缓存起来,但如果很多goroutine竞争一个chan性能肯定是问题.....由于golang团队认识到这个...阅读全文

博文 2015-06-17 20:06:14 yongjian_lian

Go 1.9 sync.Map揭秘

本文为转载,原文链接 在Go 1.6之前, 内置的map类型是部分goroutine安全的,并发的读没有问题,并发的写可能有问题。自go 1.6之后, 并发地读写map会报错,这在一些知名的开源库中都存在这个问题,所以go 1.9之前的解决方案是额外绑定一个锁,封装成一个新的struct或者单独使用锁都可以。 本文带你深入到sync.Map的具体实现中,看看为了增加一个功能,代码是如何变的复杂的,以及作者在实现sync.Map的一些思想。 有并发问题的map 官方的faq已经提到内建的map不是线程(goroutine)安全的。 首先,让我们看一段并发读写的代码,下列程序中一个goroutine一直读,一个goroutine一只写同一个键值,即即使读写的键不相同,而且map也没有"扩容"等操...阅读全文

博文 2017-07-29 17:05:12 Kotexy

golang中sync.RWMutex和sync.Mutex区别

golang中sync包实现了两种锁Mutex (互斥锁)和RWMutex(读写锁),其中RWMutex是基于Mutex实现的,只读锁的实现使用类似引用计数器的功能. type Mutex func (m *Mutex) Lock() func (m *Mutex) Unlock()type RWMutex func (rw *RWMutex) Lock() func (rw *RWMutex) RLock() func (rw *RWMutex) RLocker() Locker func (rw *RWMutex) RUnlock() func (rw *RWMutex) Unlock() 其中Mutex为互斥锁,Lock()加锁,Unlock()解锁,使用Lock()加锁后,便不能再次...阅读全文

博文 2015-06-17 20:03:41 chenbaoke

测试golang中的多核多线程

"并发 (concurrency)" 和 "并行 ( parallelism)" 是不同的。在单个 CPU 核上,线程通过时间片或者让出控制权来实现任务切换,达到 "同时" 运⾏多个任务的⺫的,这就是所谓的并发。但实际上任何时刻都只有一个任务被执行,其他任务通过某种算法来排队。多核 CPU 可以让同⼀进程内的 "多个线程" 做到真正意义上的同时运,它们之间不需要排队 (依然会发生排队,因为线程数量可能超出 CPU 核数量,还有其他的进程等等。这里说的是一个理想状况),这才是并行。除了多核,并行计算还可能是多台机器上部署运行。 package main import ( "fmt" "runtime" ) func test(c chan bool, n int) { x := 0 for i...阅读全文

博文 2015-12-24 05:00:02 zhjih123

golang互斥锁跟读写锁

golang中sync包实现了两种锁Mutex (互斥锁)和RWMutex(读写锁),其中RWMutex是基于Mutex实现的,只读锁的实现使用类似引用计数器的功能. type Mutex func (m *Mutex) Lock() func (m *Mutex) Unlock() type RWMutex func (rw *RWMutex) Lock() func (rw *RWMutex) RLock() func (rw *RWMutex) RLocker() Locker func (rw *RWMutex) RUnlock() func (rw *RWMutex) Unlock() 1、互斥锁 其中Mutex为互斥锁,Lock()加锁,Unlock()解锁,使用Lock()加锁...阅读全文

博文 2017-01-18 11:00:17 tree2013

谈谈go语言编程的并发安全

问题起因 在分布式存储开源项目 Weed-FS 中, 我发现了一个地方非并发安全(not concurrency-safety), 所以提交了一个 Weed-FS-PullRequest-75 来进行加锁保护。 简化这个问题如下: 当有一个变量, 有一个 goroutine 会对它进行写操作, 其他 goroutine 对它进行读操作。 是否需要对这个变量进行加锁保护。 我觉得不同goroutine并发读写同一个变量, 需要加锁, 这应该是天经地义的常识。 但是这个 PullRequest 居然出乎意料的被作者反驳了。 作者的理由是: 只有一个 goroutine 在写,其他 goroutine 在读,不需要加锁。 但是这样的观点我实在无法苟同, 因为在我的 C/C++ 开发经验中,这是必然...阅读全文

博文 2015-02-15 18:32:00 YanyiWu

golang 锁的使用

sync.mutex 加锁后禁止其他地方读或写,这个适用于可能出现的在不同go程中修改同一个数据 sync.rwmutex 的lock 和 unlock 的使用和sync.mutex类似 sync.rwmutex 的rlock和runlock的使用适用于要读取数据,防止在读取的同时可能出现的别的地方写入 而导致的读取失...阅读全文

博文 2015-10-15 19:00:15 徐学良

golang配置文件热更新

配置文件热更新是服务器程序的一个基本功能,通过热更新可以不停机调整程序的配置,特别是在生产环境可以提供极大的便利,比如发现log打得太多了可以动态调高日志等级,业务逻辑参数变化,甚至某个功能模块的开关等都可以动态调整。 每种语言都有自己的热更新实现方式,在golang里面我看到了有人采用了一种错误的实现方式,如下: type Config struct { Test1 string `json:"Test1"` Test2 int `json:"Test2"` } var ( config *Config ) func loadConfig() { f, err := ioutil.ReadFile("config.json") if err != nil { fmt.Println("lo...阅读全文

博文 2017-02-26 03:00:30 石匠

golang 互斥锁 sync.Mutex

一、介绍 sync.Mutex为互斥锁(也叫全局锁),Lock()加锁,Unlock()解锁。 二、场景 适用于场景: 读写次数不确定的场景(读写次数没有明显区别),同时只能一个读或者写 三、代码测试 正确示范 package main import ( "fmt" "sync" "runtime" ) func main() { runtime.GOMAXPROCS(runtime.NumCPU()) for i := 0; i <= 100; i++ { wg.Add(1) go add(i) } wg.Wait() } var s = 1000 var lock sync.Mutex var wg = &sync.WaitGroup{} func add(count int) { lo...阅读全文

博文 2019-06-27 00:32:56 清晨的麦田

golang互斥锁的一个案例

package main import ( "fmt" "runtime" "sync" ) type Counter struct { mu sync.Mutex x int64 } func (c *Counter) Inc() { c.mu.Lock() defer c.mu.Unlock() c.x++ } func main() { runtime.GOMAXPROCS(runtime.NumCPU()) c := Counter{} var wait sync.WaitGroup wait.Add(4) for k := 4; k > 0; k-- { go func() { for i := 2500000; i > 0; i-- { c.Inc() } wait.Done()...阅读全文

博文 2016-11-24 08:00:10 tree2013

go中利用hmset替换hset来提高redis的存取效率及并发goroutine可能遇到的问题

go 中直接利用hset向redis存入数据效率较低,当要存入的数据已知时,可以利用hmset 来替换hset进行存储。 var args []interface{}{"myhash"} for key,value := range fvs { args = append(args, key, value) } _, err := conn.Do("HMSET", args...) 注:fvs为对应的key,value的map映射,将该映射关系存入到redis中名字为myhash的域中, args...表示args slice中的顺序的所有元素。 hmset存储速度相对hset已经很快,但是利用go中goroutine并发hmset能取得更好的存储效果吗?答案是否定的。 当利用多个(10个)...阅读全文

博文 2015-06-18 09:02:12 chenbaoke

Go语言内存分配器设计

Go语言的整个内存管理子系统主要由两部分组成——内存分配器和垃圾收集器(gc)。十一小长假期为了避开我泱泱大国的人流高峰,于是在家宅了3天把Go语言的内存分配器部分的代码给研究了一番,总的来说还是非常酷的,自己也学到了不少的东西,就此记录分享一下。整个内存分配器完全是基于Google自家的tcmalloc的设计重新实现了一遍,因此,想看看Go语言的内存分配器实现的话,强烈建议先读一读tcmalloc的介绍文档,然后看看Go runtime的malloc.h源码文件的注释介绍,这样基本就大概了解Go语言内存分配器的设计了。 Go的内存分配器主要也是解决小对象的分配管理和多线程的内存分配问题。(后面提到的内存分配器都是指代的Go语言实现的内存分配器)。内存分配器以32k作为对象大小的定夺标准,小...阅读全文

博文 2014-11-12 17:25:06 skoo

golang 多线程查找文件内容

1 package main 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "strings" 9 ) 10 11 var matchCount = 0 12 var ch = make(chan int, 512) 13 14 func findFile(path string, text string) { 15 var pathArray [100]string 16 var count = 0 17 filepath.Walk(path, func(path string, info os.FileInfo, err error) error { 18 if err != nil { 19 } 20 //f...阅读全文

博文 2015-02-28 03:00:01 modprobe

Go 1.9 sync.Map揭秘

目录 [−] 有并发问题的mapGo 1.9之前的解决方案sync.MapLoadStoreDeleteRangesync.Map的性能其它 在Go 1.6之前, 内置的map类型是部分goroutine安全的,并发的读没有问题,并发的写可能有问题。自go 1.6之后, 并发地读写map会报错,这在一些知名的开源库中都存在这个问题,所以go 1.9之前的解决方案是额外绑定一个锁,封装成一个新的struct或者单独使用锁都可以。 本文带你深入到sync.Map的具体实现中,看看为了增加一个功能,代码是如何变的复杂的,以及作者在实现sync.Map的一些思想。 有并发问题的map 官方的faq已经提到内建的map不是线程(goroutine)安全的。 首先,让我们看一段并发读写的代码,下列程序中...阅读全文

博文 2017-07-13 02:24:09 smallnest

golang中读写锁RWMutex和通用锁Mutex的使用

golang中sync包实现了两种锁Mutex (互斥锁)和RWMutex(读写锁),其中RWMutex是基于Mutex实现的,只读锁的实现使用类似引用计数器的功能. type Mutex func (m *Mutex) Lock() func (m *Mutex) Unlock()type RWMutex func (rw *RWMutex) Lock() func (rw *RWMutex) RLock() func (rw *RWMutex) RLocker() Locker func (rw *RWMutex) RUnlock() func (rw *RWMutex) Unlock() 其中Mutex为互斥锁,Lock()加锁,Unlock()解锁,使用Lock()加锁后,便不能再次...阅读全文

博文 2017-03-05 06:03:01 skh2015java

深入理解Go 1.9 sync.Map

Go官方的faq已经提到内建的map不是线程(goroutine)安全的。在Go 1.6之前, 内置的map类型是部分goroutine安全的,并发的读没有问题,并发的写可能有问题。自go 1.6之后, 并发地读写map会报错,这在一些知名的开源库中都存在这个问题,所以go 1.9之前的解决方案是额外绑定一个锁,封装成一个新的struct或者单独使用锁都可以。另外笔者在go 1.9之前通常是使用concurrent-map来解决这类问题,但是不是所有的第三方库都以此来解决问题。 我们先来看看这个代码样例:程序中一个goroutine一直读,一个goroutine一直写同一个键值,即使读写的键不相同,而且map也没有"扩容"等操作,代码还是会报错的,错误信息是: fatal error: co...阅读全文

博文 2017-12-19 12:01:01 终于19岁

go database/sql包sql.Open不是长连接

sql.Open 不会创建连接 ,只会创建一个DB实例,同时会创建一个go程来管理该DB实例的一个连接池(是长连接,但不是在Open的时候创建)。 在调用Begin()取一个连接,回滚或者提交得时候归还。如果你直接使用时Exec()执行,则每次会从连接池里面取出一个连接,到Exec执行完毕的时候归还。可以通过参数来调节连接池的大小。 golang sql包已经做了并发处理,自己通过channel的方式维护了一个连接池,所以没有必要在go程中加锁共享。 关于每次sql.Open,我觉得应该是一个不恰当的做法,这会导致连接得不到重用,并产生过多的短时间关闭的连接,给数据库造成没必要的压力...阅读全文

博文 2015-12-23 04:00:01 s630405377

你不得不知道的sync.Map源码分析

sync.Map源码分析 背景 众所周知,go普通的map是不支持并发的,换而言之,不是线程(goroutine)安全的。博主是从golang 1.4开始使用的,那时候map的并发读是没有支持,但是并发写会出现脏数据。golang 1.6之后,并发地读写会直接panic: fatal error: concurrent map read and map write package main func main() { m := make(map[int]int) go func() { for { _ = m[1] } }() go func() { for { m[2] = 2 } }() select {} } 所以需要支持对map的并发读写时候,博主使用两种方法: 第三方类库 conc...阅读全文

博文 2018-06-10 19:34:36 梦朝思夕

利用 Redis 锁解决高并发问题

这里我们主要利用 Redis 的 setnx 的命令来处理高并发。 setnx 有两个参数。第一个参数表示键。第二个参数表示值。如果当前键不存在,那么会插入当前键,将第二个参数做为值。返回 1。如果当前键存在,那么会返回0。 创建库存表 CREATE TABLE `storage` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `number` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1 设置初始库存为10 创建订单表 CREATE TABLE `order` ( `id` int(11) u...阅读全文

博文 2019-05-07 19:34:58 51reboot

go 官方版本的日志模块为什么加锁那么多

看了下go的log模块代码,写一条日志的做法是 1,拼接日志内容 2,加锁 3,写文件 4,解锁。 这个做法在协程很多的情况下,效率比较低。 官方为啥没有提供一个高效率的版本呢? 我自己撸了一个,也就200多行代码(https://github.com/Titanarthas/s_g_log) 对比测试了下,50000个协程,每个协程写11条日志。 官方版本的log耗时是6秒多,我自己写的版本是2.4秒,也没发现我的实现有啥问...阅读全文

golang map数据结构不能并发读写问题

fatal error: concurrent map writes 以上这个错误你遇到过么? 问题由来 今天,我在编码并发测试过程中遇到一个问题直接致死整个进程。我们知道golang 中只要有一个goroutine发生panic整个进程都挂了。当时一脸萌比。开始检查堆栈信息。 问题分析 起初我查阅了相关问题解决方案。大致就是多线程操作map数据结构一定要加锁。否则肯定要出现这个错误。我查看我的代码,我认为我写的map结构都加了锁,附加锁方式: 通用锁 type Demo struct { Data map[string]string Lock sync.Mutex } func (d Demo) Get(k string) string{ d.Lock.Lock() defer d.Loc...阅读全文

博文 2016-11-17 14:00:02 zqg5258423

Go基础-map

// xuhh_go_map project /* 1.map的特点: a.map是go语言的内置引用类型,所以多个map指向同一个底层的情况下,一个值发生变化,全部发生变化 b.map是无序的,每次迭代的顺序都是不确定的。 c.map只有 len 没有 cap。 d.map不是线程安全的,在多个go-routine中使用的时候,要加锁。 e.map[key]value key 必须支持 运算符(== 、!= )的操作,例如 number/string/pointer/array/struct/interface value 可以是任意类型。 2.map的创建: a. new 进行创建 mapA := new(map[int]string) *mapA = map[int]string{} ...阅读全文

博文 2015-06-17 23:08:20 xuheazx

Go语言之Cond

自公众号:灰子学技术原文链接:https://mp.weixin.qq.com/s/9FjBJVhRBVSBV4CVpCfChgGolang的sync包中的Cond实现了一种条件变量,主要用来解决多个读协程等待共享资源变成ready的场景。在使用Cond的时候,需要特别注意下:每个Cond都会关联一个Lock(*sync.Mutex or *sync.RWMutex),当修改条件或者调用Wait方法时,必须加锁,保护condition。1. Cond的介绍:定义如下所示:​​Cond相关API介绍, Cond主要有三个函数构成,Broadcast(), Signal(), Wait()。1.1. Broadcast()用来唤醒所有的处于等待c状态的协程,如果没有等待的协程,该函数也不会报错。...阅读全文

博文 2019-12-25 13:03:52 ZhDavis

<5> go 上下文传递context

有go有channal,slick,map,interface,func等等,其中func可以当作参数传递的这个功能也是很多动态语言支持的。 现在看下怎么使用 import ( "fmt" ) type Do struct { Name string } func (this Do) Lock() { fmt.Println(this.Name + " Lock ...") } func (this Do) UnLock() { fmt.Println(this.Name + " Unlock ~") } // 假设需要做加锁解锁 func Say() { do := Do{Name: "Say"} do.Lock() defer do.UnLock() fmt.Println("say d...阅读全文

博文 2016-01-18 15:00:04 a11101171

golang中的map与sync.Map

map map的底层实现 golang中的map采用了HashTable的实现,通过数组+链表实现的。一个哈希表会有一定数量的桶,哈希表将键值对均匀存储到这些桶中。哈希表在存储键值对时,会先用哈希函数把键值转换为哈希值,哈希表先用哈希值的低几位去定位到一个哈希桶,然后再去这个哈希桶中查找这个键。由于键值对总是被捆绑在一起存在,一旦找到了键,就找到了值。go的字典中,每一个键值对都是它的哈希值代表的,字典不会独立存储任何键的键值,但会独立存储他们的哈希值 map的键类型不能是哪些类型 不能是函数类型、字典类型、切片类型。 原因:go语言规范规定,键类型的值之间必须可以施加==操作符和!=操作符,即必须支持判等操作,由于函数类型,字典类型,切片类型不支持判等操作 如果键类型是接口类型,那么键值的...阅读全文

博文 2019-04-10 23:34:40 xixisuli

golang sync.pool对象复用 并发原理 缓存池

golang sync.pool对象复用 并发原理 缓存池 在go http每一次go serve(l)都会构建Request数据结构。在大量数据请求或高并发的场景中,频繁创建销毁对象,会导致GC压力。解决办法之一就是使用对象复用技术。在http协议层之下,使用对象复用技术创建Request数据结构。在http协议层之上,可以使用对象复用技术创建(w,*r,ctx)数据结构。这样即可以回快TCP层读包之后的解析速度,也可也加快请求处理的速度。 先上一个测试: //测试平台 i5 3.8GHz 4核 bPool := sync.Pool{ New: func() interface{} { b := make([]byte,1024) return &b }, } t1 := time.Now...阅读全文

博文 2018-11-16 19:34:46 fjxCode

不要对 I/O 上锁

锁可用于同步操作。但如果使用不当的话,也会引发显著的性能问题。一个比较常见出问题的地方是 HTTP handlers 处。尤其很容易在不经意间就会锁住网络 I/O。要理解这种问题,我们最好还是来看一个例子。这篇文章中,我会使用 Go。 为此,我们需要编写一个简单的 HTTP 服务器用以报告它接收到的请求数量。所有的代码可以从 [这里](https://github.com/gobuildit/gobuildit/tree/master/lock) 获得。 报告请求数量的服务看起来是这样的: ```go package main // import statements // ... const ( payloadBytes = 1024 * 1024 ) var ( mu sync.Mute...阅读全文

博文 2018-05-05 17:57:33 snowInPluto

Go语言之RWMutex

自“灰子学技术”,原文链接:https://mp.weixin.qq.com/s/0nfjNsFNIrMhYJMf3P-sEw本篇文章,笔者主要来介绍读写锁的一种Go语言的实现方式RWMutex。1.基本概念读写锁:是计算机程序的并发控制的一种同步机制,也称“共享-互斥锁”、多读者-单写者锁。读操作可并发重入,写操作是互斥的。主要适用的场景是:读多写少的业务场景。这种场景下如果每次读写都使用互斥锁那么整个效率就会变得很低。因为只是读的话并不需要互斥锁来锁住数据,只有写操作的时候需要互斥锁,而读写结合的时候,也是需要加锁的,不然的话会导致读的数据不一定是期望的。对于RWMutex的规则如下:1、可以随便读,多个goroutine同时读。2、写的时候,不能读也不能写。主要有下面四个API构成,读...阅读全文

博文 2019-12-23 09:51:08 ZhDavis

Go语言之RWMutex

自“灰子学技术”,原文链接:https://mp.weixin.qq.com/s/0nfjNsFNIrMhYJMf3P-sEw本篇文章,笔者主要来介绍读写锁的一种Go语言的实现方式RWMutex。1.基本概念读写锁:是计算机程序的并发控制的一种同步机制,也称“共享-互斥锁”、多读者-单写者锁。读操作可并发重入,写操作是互斥的。主要适用的场景是:读多写少的业务场景。这种场景下如果每次读写都使用互斥锁那么整个效率就会变得很低。因为只是读的话并不需要互斥锁来锁住数据,只有写操作的时候需要互斥锁,而读写结合的时候,也是需要加锁的,不然的话会导致读的数据不一定是期望的。对于RWMutex的规则如下:1、可以随便读,多个goroutine同时读。2、写的时候,不能读也不能写。主要有下面四个API构成,读...阅读全文

博文 2019-12-21 20:32:49 灰常出色

golang sync map思考总结

一、核心结构体先贴一下 type Map struct { mu Mutex //互斥锁,用于锁定dirty map read atomic.Value //优先读map,支持原子操作,注释中有readOnly不是说read是只读,而是它的结构体。read实际上有写的操作 dirty map[interface{}]*entry // dirty是一个当前最新的map,允许读写 misses int // 主要记录read读取不到数据加锁读取read map以及dirty map的次数,当misses等于dirty的长度时,会将dirty复制到read } type readOnly struct { m map[interface{}]*entry amended bool // true...阅读全文

博文 2019-03-05 22:34:50 凯文不上班

图解golang里面的读写锁实现与核心原理分析

基础筑基 读写锁的特点 读写锁区别与互斥锁的主要区别就是读锁之间是共享的,多个goroutine可以同时加读锁,但是写锁与写锁、写锁与读锁之间则是互斥的 写锁饥饿问题 因为读锁是共享的,所以如果当前已经有读锁,那后续goroutine继续加读锁正常情况下是可以加锁成功,但是如果一直有读锁进行加锁,那尝试加写锁的goroutine则可能会长期获取不到锁,这就是因为读锁而导致的写锁饥饿问题 基于高低位与等待队列的实现 在说golang之前介绍一种JAVA里面的实现,在JAVA中ReentrantReadWriteLock实现采用一个state的高低位来进行读写锁的计数,其中高16位存储读的计数,低16位存储写的计数,并配合一个AQS来实现排队等待机制,同时AQS中的每个waiter都会有一个st...阅读全文

博文 2019-12-25 17:33:47 千锋IJava

golang 并发安全Map以及分段锁的实现

涉及概念 并发安全Map 分段锁 sync.Map CAS ( Compare And Swap ) 双检查 分断锁 type SimpleCache struct { mu sync.RWMutex items map[interface{}]*simpleItem }     在日常开发中, 上述这种数据结构肯定不少见,因为golang的原生map是非并发安全的,所以为了保证map的并发安全,最简单的方式就是给map加锁。    之前使用过两个本地内存缓存的开源库, gcache, cache2go,其中存储缓存对象的结构都是这样,对于轻量级的缓存库,为了设计简洁(包含清理过期对象等 ) 再加上当需要缓存大量数据时有redis,memcache等明星项目解决。 但是如果抛开这些因素遇到真...阅读全文

博文 2019-03-10 03:34:40 薛薛薛

Innodb中的事务隔离级别和锁的关系

前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式。同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力。所以对于加锁的处理,可以说就是数据库对于事务处理的精髓所在。这里通过分析MySQL中InnoDB引擎的加锁机制,来抛砖引玉,让读者更好的理解,在事务处理中数据库到底做了什么。 #一次封锁or两段锁?因为有大量的并发访问,为了预防死锁,一般应用中推荐使用一次封锁法,就是在方法的开始阶段,已经预先知道会用到哪些数据,然后全部锁住,在方法运行之后,再全部解锁。这种方式可以有效的避免循环死锁,但在数据库中却不适用,因为在事务开始阶段,数据库并不知道会用到哪些数据。数据库遵循的是两段锁协议,将事务分成两个...阅读全文

博文 2017-12-05 03:13:14

【golang】小技巧-sync.Map解决map并发不安全问题

golang中的map在并发下是不安全的,如果同时读写会出现: type M struct { Map map[string]string } // Set ... func (m *M) Set(key, value string) { m.Map[key] = value } // Get ... func (m *M) Get(key string) string { return m.Map[key] } func main() { c := M{Map: make(map[string]string)} wg := sync.WaitGroup{} for i := 0; i < 21; i++ { wg.Add(1) go func(n int) { k, v := strcon...阅读全文

博文 2020-05-15 17:38:32 dongzaidong

用生产者消费者理解golang channel

golang实现多生产者多消费者: package main import ( "fmt" "time" ) func consumer(cname string, ch chan int) { for i := range ch { fmt.Println("consumer--", cname, ":", i) } fmt.Println("ch closed.") } func producer(pname string, ch chan int) { for i := 0; i < 4; i++ { fmt.Println("producer--", pname, ":", i) ch <- i } } func main() { //用channel来传递"产品", 不再需要自己去...阅读全文

博文 2017-07-23 10:06:26 zengfan

GO 锁

"锁" 在线程同步的时候是非常重要的, 如果是文件锁能够防止误写, 当然锁的用法也比较简单, 操作前 加锁, 操作完成 解锁, 当有其他线程操作的时候, 需要等待, 直到其他线程解锁, 方能继续操作. var lock *sync.Mutex lock = new(sync.Mutex) lock.Lock() ... ... // 处理操作的逻辑 lock.Unlock() 如果在解锁之前再次进行加锁,会进入死锁状态 如果是文件锁, 会分为读锁 RLock(), 写锁 WLock() 以及 读写锁 RWLock() var lock *sync.RWMutex lock = new(sync.RWMutex) lock.RLock() ... ... // 处理文件操作的逻辑 lock.R...阅读全文

博文 2017-02-10 14:45:03 yin32167

golang配置文件热更新

配置文件热更新是服务器程序的一个基本功能,通过热更新可以不停机调整程序的配置,特别是在生产环境可以提供极大的便利,比如发现log打得太多了可以动态调高日志等级,业务逻辑参数变化,甚至某个功能模块的开关等都可以动态调整。 每种语言都有自己的热更新实现方式,在golang里面我看到了有人采用了一种错误的实现方式,如下: type Config struct { Test1 string `json:"Test1"` Test2 int `json:"Test2"` } var ( config *Config ) func loadConfig() { f, err := ioutil.ReadFile("config.json") if err != nil { fmt.Println("lo...阅读全文

博文 2017-03-17 05:52:28 失去梦想的咸鱼

基于多 goroutine 实现令牌桶

前言 令牌桶是一种常见用于控制速率的控流算法。原理于 Wikipedia 上描述如下: 每秒会有 r 个令牌被放入桶中,即每 1 / r 秒向桶中放入一个令牌。 一个桶最多可以存放 b 个令牌。当令牌被放入桶时,若桶已满,则令牌被直接丢弃。 当一个 n 字节的数据包抵达时,消耗 n 个令牌,然后放行之。 若桶中的令牌不足 n ,则该数据包要么被缓存要么被丢弃。 下面我们便根据上述描述,使用 Go 语言,基于多 goroutine ,来实现是一个并发安全的令牌桶。后述代码的完整实现的仓库地址在:https://github.com/DavidCai19... 。 基本设计 最基本的结构便是,定义一个令牌桶 struct ,该 struct 每一个新生成的令牌桶实例,各自带有一个 gorouti...阅读全文

博文 2017-02-10 02:38:46 菜菜蔡伟

golang 锁

手册中有点难懂,自己写个例子。 package main import ( "fmt" "time" ) func main() { // 不想用time sleep // 挂起通道 不让主main退出,我想看结果 //ch := make(chan bool) public := 1 go func() { fmt.Println("执行了1操作") for i := 0; i < 2; i++ { time.Sleep(time.Microsecond * 100) public++ fmt.Println(public) } }() go func() { fmt.Println("执行了2操作") for i := 0; i < 2; i++ { time.Sleep(time.Mi...阅读全文

博文 2020-05-06 11:34:27 蛐蛐儿阳

golang 中 sync.Mutex 和 sync.RWMutex

介绍 golang 中的 sync 包实现了两种锁: Mutex:互斥锁 RWMutex:读写锁,RWMutex 基于 Mutex 实现 Mutex(互斥锁) Mutex 为互斥锁,Lock() 加锁,Unlock() 解锁 在一个 goroutine 获得 Mutex 后,其他 goroutine 只能等到这个 goroutine 释放该 Mutex 使用 Lock() 加锁后,不能再继续对其加锁,直到利用 Unlock() 解锁后才能再加锁 在 Lock() 之前使用 Unlock() 会导致 panic 异常 已经锁定的 Mutex 并不与特定的 goroutine 相关联,这样可以利用一个 goroutine 对其加锁,再利用其他 goroutine 对其解锁 在同一个 gorout...阅读全文

博文 2017-07-31 09:06:25 WangZZ

Go36-34,35-并发安全字典(sync.Map)

并发安全字典(sync.Map) 之前的几篇,几乎已经把Go语言自带的同步工具都讲过了。这篇要讲的是一个并发安全的高级数据结构:sync.Map。 原生字典 Go语言自带的字典类型map,就是原生字典,并不是并发安全的。 在使用原生字典的时候,应该在启动goroutine之前就完成字典的初始化和赋值。或者更高级的做法是,可以在goroutine中,在首次使用的时候通过sync.Once来并发安全的完成初始化和赋值的操作,达到一个延迟初始化的优化效果。之后在使用字典的时候,就只能获取其中的内容,不能再对其进行修改了。这个在讲sync.Once时,在最后有示例。 如果是需要一个并发安全的,可以修改内容的原生字典,也不是太麻烦。加上互斥锁或读写锁就可以轻松实现了。下面就是一个自制的简易并发安全字典...阅读全文

博文 2019-02-01 09:35:13 骑士救兵

golang笔记之基于共享变量的并发

介绍 golang 中的 sync 包实现了两种锁: Mutex:互斥锁 RWMutex:读写锁,RWMutex 基于 Mutex 实现 Mutex(互斥锁) Mutex 为互斥锁,Lock() 加锁,Unlock() 解锁 在一个 goroutine 获得 Mutex 后,其他 goroutine 只能等到这个 goroutine 释放该 Mutex 使用 Lock() 加锁后,不能再继续对其加锁,直到利用 Unlock() 解锁后才能再加锁 在 Lock() 之前使用 Unlock() 会导致 panic 异常 已经锁定的 Mutex 并不与特定的 goroutine 相关联,这样可以利用一个 goroutine 对其加锁,再利用其他 goroutine 对其解锁 在同一个 gorout...阅读全文

博文 2019-05-06 15:46:55 月下独酌100

pid file解读

pid file pid file 是什么? pid file是一个文件,里面保存了后台程序的pid。 pid file 的作用? 其他程序可以通过这个pid文件,获取这个后台程序的pid,然后执行一些任务。 当别的用户启动这个后台程序的时候,可以检查这个文件,防止出现多个相同后台程序。 如何实现pid file的功能? 使用pid file,需要几个步骤: 找个目录创建这个pid文件,在linux系统中,一般放在/var/run/program.pid, program是运行的程序名。 获取进程pid,并且写入上面的文件中。 pid file的使用 读取文件中的pid,给其他程序或者自身程序使用。 通过几种方法判定读取的pid存在 向这个pid发送0信号kill(0, pid),存在返回成...阅读全文

博文 2019-04-30 10:34:40 今生路人甲

扣丁学堂解析golang并发安全Map以及分段锁的实现方法

今天扣丁学堂区块链培训老师给大家介绍一篇关于golang 并发安全Map以及分段锁的实现方法详解,首先涉及概念:并发安全Map、分段锁、sync.Map、CAS(CompareAndSwap)、双检查等下内容,下面我们一起来看一下吧。 分断锁type SimpleCache struct { mu sync.RWMutex items map[interface{}]*simpleItem}在日常开发中,上述这种数据结构肯定不少见,因为golang的原生map是非并发安全的,所以为了保证map的并发安全,最简单的方式就是给map加锁。之前使用过两个本地内存缓存的开源库,gcache,cache2go,其中存储缓存对象的结构都是这样,对于轻量级的缓存库,为了设计简洁(包含清理过期对象等)再加上...阅读全文

博文 2019-03-11 16:34:50 扣丁学堂

技术进阶:Redis分布式锁的应用(一)

导入 之前一直在给大家写docker相关的东西,当然docker的东西也会继续的写,在此插一篇《关于Redis分布式锁的应用》开开荤腥。 背景 同一主机同一进程不同的线程,如何同步访问一段代码块呢? Java有synchronized synchronized(this) { } Golang有sync工具包 var mutex sync.Mutex //加锁mutex mutex.Lock() do Something··· //解锁mutex mutex.Unlock() PHP 因为PHP没有多线程的概念,对PHP而言,普遍的是多进程,PHP的多个多进程之间同步访问,可以通过文件锁来实现。 $fp = fopen("logs/lock.l", "a+"); if (flock($fp,...阅读全文

博文 2018-09-02 20:34:43 指尖流年

由浅入深聊聊Golang的sync.Map

前言 今天在技术群中有小伙伴讨论并发安全的东西,其实之前就有写过map相关文章:由浅入深聊聊Golang的map。但是没有详细说明sync.Map是怎么一回事。 回想了一下,竟然脑中只剩下“两个map、一个只读一个读写,xxxxx”等,关键词。有印象能扯,但是有点乱,还是写一遍简单记录一下吧。 1.为什么需要sync.Map? 2.sync.Map如何使用? 3.理一理sync.Map源码实现? 4.sync.Map的优缺点? 5.思维扩散? 正文 1.为什么需要sync.Map? 关于map可以直接查看由浅入深聊聊Golang的map,不再赘述。 为什么需要呢? 原因很简单,就是:map在并发情况虚啊,只读是线程安全的,同时写线程不安全,所以为了并发安全 & 高效,官方实现了一把。 1.1...阅读全文

博文 2019-07-23 17:44:18 咖啡色的羊驼