mirror of
https://github.com/unknwon/the-way-to-go_ZH_CN.git
synced 2025-08-11 22:06:51 +08:00
第九章第三节,锁和sync包的内容翻译 09.3.md
This commit is contained in:
32
eBook/09.3.md
Normal file
32
eBook/09.3.md
Normal file
@@ -0,0 +1,32 @@
|
||||
#9.3锁和sync包
|
||||
在一些复杂的程序中,通常通过不同线程执行不同应用来实现程序的并发。当不同线程要使用同一个变量时,经常会出现一个问题:无法预知变量被不同线程修改的顺序!(这通常被称为资源竞争,指不同线程对同一变量使用的竞争。)显然这无法让人容忍,那我们该如何解决这个问题呢?
|
||||
|
||||
经典的做法是一次只能让一个线程对共享变量进行操作。当变量被一个线程改变时(临界区),我们为它上锁,直到这个线程执行完成并解锁后,其他线程才能访问它。
|
||||
|
||||
特别是我们之前章节学习的map类型是不存在锁的机制来实现这种效果(出于对性能的考虑),所以map类型是非线程安全的.当并行访问一个共享的map类型的数据,map数据将会出错。
|
||||
|
||||
在Go语言中这种锁的机制是通过sync包中Mutex来实现的。sync来源于"synchronized"一词,这意味着线程将有序的对同一变量进行访问。
|
||||
|
||||
sync.Mutex是一个互斥锁,它的作用是守护在临界区入口来确保同一时间只能有一个线程进入临界区。
|
||||
|
||||
假设info是一个需要上锁的放在共享内存中的变量。通过包含Mutex来实现的一个典型例子如下:
|
||||
|
||||
import “sync”
|
||||
type Info struct {
|
||||
mu sync.Mutex
|
||||
// ... other fields, e.g.: Str string
|
||||
}
|
||||
如果一个函数想要改变这个变量可以这样写:
|
||||
|
||||
func Update(info *Info) {
|
||||
info.mu.Lock()
|
||||
// critical section:
|
||||
info.Str = // new value
|
||||
// end critical section
|
||||
info.mu.Unlock()
|
||||
}
|
||||
还有一个很有用的例子是通过Mutex来实现一个可以上锁的共享缓冲器:
|
||||
|
||||
type SyncedBuffer struct {
|
||||
lock sync.Mutex
|
||||
buffer bytes.Buffer
|
Reference in New Issue
Block a user