美文网首页
【读书札记】golang并发编程

【读书札记】golang并发编程

作者: wangrui927 | 来源:发表于2018-03-26 18:38 被阅读0次

来自图书《Concurrency In Go》

1,Race Conditions 竞争关系

var data int
go func() {
    data ++
}()
if data == 0{
    fmt.Printf("value is %v \n", data)
}

这样的代码就有3种可能,我们当然可以在go协程后面加上一句 time.Sleep(1*time.Second)来临时解决这个问题。但这并不是从根本上解决问题的方法,只是降低了意外结果发生的可能性,因为其并没有做到逻辑正确(logically correct)。
竞争关系是程序开发中最常见的隐蔽性bug。

2,Atomicity 原子性

考虑这点,最关键的是context或scope,也就是代码的上下文。书中例举一个例子,06年的时候暴雪起诉一家做魔兽世界外挂的公司,这公司就是在游戏运行前,将代码注入了系统操作环境的上下文中从而避开了暴雪Warden反外挂程序的监控,因为后者监控的是进程的内存上下文空间。
如 i++ 这个操作。实际上这个操作是三个步骤:
获取i的值;增加i的值;保存i的值。
这三个步骤本身都是原子性的,但叠加到一起就不是了。所以这里还要讲和原子性密切相关的两个形容词:indivisible and uninterruptible
不可分性与不可打断性。那么如果在go的并发编程中,你要保持这种原子性,你就得保证在这个特定的行为中,你的go协程没有把context暴漏给其他协程。
原子性是非常重要的,其直接关系到我们的程序代码是否真正的逻辑正确,而不是结果正确。(这句话很有启发,应该不断地询问自己,代码的逻辑是否真正地严密)

3,Memory Access Synchronization 内存访问同步

还是回到上面的例子,将代码改成

var data int
go func() { data++}()
if data == 0 {
fmt.Println("the value is 0.")
} else {
fmt.Printf("the value is %v.\n", data)
}

当我们监视代码的时候,应该标记所有会访问共享资源的代码,并称它们为Critical Section。比如上面代码中的:data++; if data ;fmt.Printf(...) 这三块代码。那么可以这样写:

var memoryAccess sync.Mutex
var value int
go func() {
    memoryAccess.Lock()
    value++
    memoryAccess.Unlock()
}()
memoryAccess.Lock()
if value == 0 {
    fmt.Printf("the value is %v.\n", value)
} else {
    fmt.Printf("the value is %v.\n", value)
}
    memoryAccess.Unlock()

这样就能保证内存访问的同步性,但是需要注意的是,这绝对不是golang语言推荐的编码风格!只是希望让开发者意识到,任何时候如果想接触数据变量的内存空间,都要使用Lock,并在使用完数据后解锁。(defer lock.unlock())
直到现在为止,我们都没有真正地解决竞争关系。因为即便加了锁,我们任然无法确定上面代码具体的执行顺序。到底是go协程先完成了,还是下面的判断动作先完成。
在后面会去探讨这些困难相应的解决方案。现在我们应该带着2个问题:
a,在我的代码中,Critical Section是否重复的进入和退出(这里是指代码块的enter和exit)
b,Critical Section的大小规模应该如何控制

4,Deadlocks,Livelocks and Starvation 死锁、活锁和 (挨饿在计算机名词中应该怎么翻译)

解决了前面的问题,还有各种锁问题等待着我们。死锁,是指程序陷入并发进程互相等待而阻塞的异常状态。在这种状态下,除非外部终止,否则程序无法恢复正常。golang的运行环境会尝试去探测一些死锁的存在,但无法从根本上预防死锁的发生。

相关文章

  • 【读书札记】golang并发编程

    来自图书《Concurrency In Go》 1,Race Conditions 竞争关系 这样的代码就有3种可...

  • Golang的并发编程

    golang是为并发而生的语言。优雅的并发编程范式,完善的并发支持,出色的并发性能是golang区别于其他语言的一...

  • Golang的并发编程

    Golang中的并发编程 Golang语言中,并发使用的协程的机制,实现起来也是十分的方便,使用go关键字即可。 ...

  • Golang并发编程

    Go 语言简介(下)— 特性 并发不是并行Go负载均衡 一个Go例程(Goroutines)就是一个和其它Go例程...

  • Golang并发编程

    在Go语言中,语言本身就已经实现和支持了并发, 我们只需要通过go关键字来开启goroutine即可。 gouro...

  • golang并发编程

    https://go101.org/article/channel-use-cases.html https://...

  • 【转载】Golang处理大数据时使用高效的Pipeline(流水

    并发是件技术活 Golang被证明非常适合并发编程,goroutine比异步编程更易读、优雅、高效。本文提出一个适...

  • Go goroutine

    Golang特色之一是支持高并发编程模型,以Goroutine作为基本的并发执行单元。 Goroutine是轻量级...

  • Golang之并发编程一

    并发基础 在说Golang的并发编程之前,先认识一下目前并发的几种实现方式: 1.多进程。操作系统实现的并发模型,...

  • GoLang并发编程3

    并发编程有两个模式 共享内存 消息 共享内存,以C语言举例 换成 GoLang

网友评论

      本文标题:【读书札记】golang并发编程

      本文链接:https://www.haomeiwen.com/subject/sqorcftx.html