在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
本文章收录于我的博客专栏读Go语言并发之道 前言:本文档是读《Go语言并发之道》一书之后的总结,按照章节进行记录。 目录 第一章 并发概述
永远不要用time.Sleep来保证你程序运行的逻辑性,这不是一种优雅的方式,更不是一种正确的方式,还可能会给你的程序留下可能潜伏许久的难以调试的bug。 我们应该使用正确的协程间通信的方式来处理资源竞争的状况。
当某些东西被定义为原子的,或具有原子性的。那在它的运行过程中,它是不可分割的或不可中断的,即使异常。 原子性的程序在并发环境中是安全的。(通常叫做并发安全/线程安全) 示例说明:我们必须在并发程序以非【原子操作】方式访问共享资源的时候,进行并发同步。 data++ 不是原子操作,它可以细分为检索、修改、存储三个操作。 示例中,goroutine和主进程同时访问data,这不是安全的共享资源访问方式。 访问同一块内存的部分也叫做临界区。
我们使用一种非常见的方式来解决上个示例的同步问题。 问题:
解决这些问题是一种艺术,继续向下看。
死锁:指的是所有并发进程都在等待其他进程释放锁。这种情况下,若没有外界干预,永远无法恢复。 活锁:活锁指的是任务或者执行者没有被阻塞,由于某些条件没有满足,导致一直重复尝试—失败—尝试—失败的过程。处于活锁的实体是在不断的改变状态,活锁有可能自行解开。 例如线程从队列中拿出一个任务来执行,如果任务执行失败,那么将任务重新加入队列,继续执行。假设任务总是执行失败,或者某种依赖的条件总是不满足,那么线程一直在繁忙却没有任何结果。 饥饿:任何情况下,并发进程都无法获得执行工作所需的所有资源。 饥饿更多指的是,有一个或多个贪婪的并发进程,它们争抢较多的共享资源,导致其他并发进程一直得不到资源,一直做无意义的等待。 这多是开发者设计不合理导致的。
第二章 对你的代码建模:顺序通信进程(CSP)
a. 大多数时候开发者们讨论的都应该是并发
CSP是是go语言设计的重要组成部分。 编写并发代码有两种方式可选,一个是CSP,另一种就是内存访问同步; 这其实就是并发模型中的两种通信方式: 1) 使用sync包就是通过共享内存来通信,这其实会降低并发程序的性能。 2) sync与其他包中可以让你执行锁,创建资源池取代goroutine。
sync包文档中有如下描述: 在Go语言的FAQ中有: 如何选择选择合适的并发通信模型? 书中原话:使用最好描述,和最简单的那个方式。 书中推荐的决策方式: Go语言的并发哲学总结:追求简洁,尽量使用channel,并且认为goroutine的使用是(几乎)没有成本的。(译文没有"几乎"二字,但个人认为添上更合理)
|
请发表评论