网站首页 > 技术文章 正文
并发性是一个程序同时做多种事情的能力,这意味着一个程序可以执行两个或多个任务,这些任务虽然大致上在同一时间内分别运行,但仍然是同一程序的一部分。并发性在现代软件中非常重要,因为很多情况下需要在不干扰程序整体流程而尽可能快地执行独立的代码片段。
Golang中的并发性是指函数独立运行的能力。goroutine协程就是能够与其他函数同时运行的函数。当函数作为协程时,它被视为一个独立的工作单元,该工作单元能够被调度,然后在可用的逻辑处理器上执行。Golang运行时调度程序具有管理所有已创建且需要处理器时间的协程的功能。调度程序将操作系统的线程绑定到逻辑处理器以执行协程。调度程序位于操作系统的顶部,控制着哪个某个逻辑处理器上运行的哪个协程有其相关的所有内容。
流行的编程语言如Java和Python通过使用线程来实现并发性。Golang有内置的实现并发性的语言结构:协程和通道。这种并发性实现方式即方便又容易使用的,被认为是一种代价低廉的轻量级的线程。通道是用于协程之间通信的管道。
通信顺序进程(简称CSP)用于描述具有多个并发模型的系统之间应该如何交互,用在两个或多个并发进程之间严重地依赖于使用通道作为传递消息的媒介,是Golang的基本魔法糖。
goroutine:协程是能够独立于启动它的函数而运行的函数。
Channels:通道是发送和接收数据的管道,为一个协程向另一个协程发送结构化数据提供了可行的方法。
在面对多任务情况时,出现两个概念:并发性和并行性,它们通常可以互换使用,它们相关联但又是不同的东西。
Concurrency:并发性是指同时处理许多任务。这意味着要在给定的时间段内程序同时管理许多任务。但是,一次只能执行一个任务。即当一个任务在等待资源的时候,程序会在这个空闲时间段处理另一个任务。这是解决问题的一种方式,程序协调处理许多同时发生的事件。
Parallelism:并行性是指同时执行许多任务。这意味着,即使有两项任务,它们可以同时连续地工作不会受到任何干扰。这是解决问题的另一种方式,并行地处理问题的不同部分以使程序更快。
并发程序有多个逻辑控制流。这些控制流可以并行运行,也可以不并行运行。通过同时执行不同的任务,并行程序可能比顺序程序运行得更快,它也可以有多个逻辑控制流。
哲学家吃晚餐的示例
五位沉默的哲学家坐在一张圆桌旁,桌上摆着几碗意大利面。叉子放在两个相邻的哲学家之间。每个哲学家必须轮流思考和吃饭。然而,哲学家只有在有左叉子和右叉子的时候才能吃意大利面。叉子只能由一个哲学家持有,因此哲学家只能在叉子没有被另一个哲学家使用的情况下使用。当一个哲学家吃完饭后,需要放下两个叉子,这样叉子才能被其他人使用。哲学家可以把叉子放在他们的右边或左边,但不能在得到两个叉子之前就开始吃东西。进食不受剩余的意大利面或胃空间的限制;假设无限的供应和无限的需求。问题是如何设计一个行为准则(并行算法),这样哲学家就不会挨饿;也就是说,每个人都可以永远在吃饭和思考之间交替,假设没有哲学家知道别人什么时候想吃东西或思考。
结果:
Table empty
Mark seated
Mark Hungry
Mark Eating
..................
..................
Haris Thinking
Haris Satisfied
Haris Left the table
Table empty
检查点同步的示例
检查点同步是多个任务同步的问题。假设有一个车间,几个工人正在装配某个机构的细节。当他们每个人完成自己的工作时,需要把细节整合在一起。先完成工作的工人在开始另一个工作之前必须等待其他人。把细节放在一起是一个检查点,在开展各自下一步工作之前必须先同步检查点。
结果:
2019/07/15 16:10:32 begin assembly cycle 1
2019/07/15 16:10:32 D worker begins part
2019/07/15 16:10:32 A worker begins part
2019/07/15 16:10:32 B worker begins part
........
2019/07/15 16:10:32 D worker completes part
2019/07/15 16:10:32 C worker completes part
2019/07/15 16:10:32 assemble. cycle 3 complete
生产者消费者问题的示例
这个问题描述了两个进程,生产者和消费者,它们共享一个公共的、固定大小的缓冲区,用作队列。生产者的工作是生成数据,将其放入缓冲区,然后重新开始。同时,消费者消费数据(即从缓冲区中移除数据)。问题是要确保生产者不会在缓冲区已满时尝试将数据添加到缓冲区中,并且消费者不会尝试从空缓冲区中删除数据。生产商的解决方案是要么进入睡眠状态,要么在缓冲区已满时丢弃数据。下一次消费者从缓冲区中移除一个数据时,它会通知生产者,生产者将再次开始填充缓冲区。同样,如果消费者发现缓冲区是空的,他们也可以进入睡眠状态。下一次生产者将数据放入缓冲区时,它会唤醒沉睡的消费者。
结果:
consume: Started
produce: Started
produce: Sending 0
produce: Sending 1
consume: Received: 0
consume: Received: 1
produce: Sending 2
produce: Sending 3
consume: Received: 2
consume: Received: 3
produce: Sending 4
produce: Done
瞌睡的理发师问题示例
理发师在理发室里有一把理发椅,在等候室里有许多椅子。理发师剪完顾客的头发后,就把顾客打发走,到等候室查看是否还有其他人在等待。如果有的话,他会把其中一个带到椅子上剪头发。如果没有,他就回到椅子上睡觉。每个顾客到了之后,都会看看理发师在做什么。如果理发师在睡觉,顾客会把他叫醒,坐在理发室的椅子上。如果理发师在理发,顾客就呆在等候室里。如果等候室里有一张空闲的椅子,顾客就坐在里面等着轮到他们。如果没有空闲的椅子,顾客就离开。
结果:
Checking waiting room: 0
Sleeping Barber - <nil>
Customer 120 checks Sleeping barber | room: 0, w 0 - customer: <nil>
Woken by 120
..............
..............
Checking waiting room: 0
No more customers for the day
吸烟者问题的示例
假设一支香烟需要三种成分:烟草、纸张和火柴。桌子周围有三个吸烟者,每一个吸烟者都有无限量的三种成分中的一种,一个吸烟者有烟草,另一个吸烟者有纸,第三个吸烟者有火柴。第四方,有着无限量的所有的供应,随机选择了一个吸烟者,并把香烟所需的供应摆上桌子。选择的吸烟者吸烟,这个过程应该无限期地重复。
结果:
Sandy, Apple, Daisy, sit with
paper, grass, match
Table chooses match: Daisy
Table: 1 grass: 1 match: 0
Table: 1 grass: 0 match: 0
Table: 0 grass: 0 match: 0
Daisy smokes a cigarette
Table chooses paper: Sandy
Table: 0 grass: 1 match: 1
Table: 0 grass: 1 match: 0
Table: 0 grass: 0 match: 0
Sandy smokes a cigarette
Table chooses match: Daisy
Table: 1 grass: 1 match: 0
Table: 1 grass: 0 match: 0
Table: 0 grass: 0 match: 0
Daisy smokes a cigarette
- 上一篇: 如何使用 Go 语言搭建企业级高并发服务器?
- 下一篇: 浅谈Go语言的并发控制
猜你喜欢
- 2024-12-01 Go 并发可视化解释 — 通道
- 2024-12-01 Go并发编程面试15题
- 2024-12-01 Go 语言并发编程实践:从入门到进阶
- 2024-12-01 Go语言编写的简单并发编程示例
- 2024-12-01 并发编程的奇技淫巧:Go语言调度器的内在工作机制
- 2024-12-01 Goroutine 并发调度模型深度解析之手撸一个高性能 goroutine 池
- 2024-12-01 每天2分钟学习GO语言编程(十九)并发简明教程
- 2024-12-01 并发编程,程序员必修课,来看go语言的巧妙实现,极为干练
- 2024-12-01 Go项目中如何限制并发数?Atomic必须掌握
- 2024-12-01 Go语言并发入门
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)