阅界资讯

并发编程(零):并发问题与讨论范围

阅阅界编辑部1阅读7分钟

《并发编程(零):并发问题与讨论范围》这篇在博客园热度很高,讲的正是大家天天碰到的事。下面帮你把要点捋出来,结尾有能直接抄的结论。

目录 1. 先明确讨论范围 2. 从一个共享变量开始 3. 两种主要的协作模型 3.1 Shared Memory:通过同步保护共享状态 3.2 Message Passing:通过消息进行协作 4. 为什么这些代码能够正确工作? 5. 语言需要定义并发语义 6. 为什么还要继续下钻到硬件? 7. 下一篇:先谈硬件 1. 先明确讨论范围 这个系列只讨论: 单机、单进程内部的并发。 也就是说,我们关注的是同一个进程中的多个执行单元。 例如: Java Thread / Virtual Thread; Go Goroutine; Python Thread / asyncio Task。 不讨论跨进程通信、分布式系统和网络通信。 2. 从一个共享变量开始 假设进程中有一个变量: [代码示例略] 现在有两个执行单元: [代码示例略] 如果 A 和 B 各执行一次,最终结果是否一定是: [代码示例略] 答案是不一定。

目录 1. 先明确讨论范围 2. 从一个共享变量开始 3. 两种主要的协作模型 3.1 Shared Memory:通过同步保护共享状态 3.2 Message Passing:通过消息进行协作 4. 为什么这些代码能够正确工作? 5. 语言需要定义并发语义 6. 为什么还要继续下钻到硬件? 7. 下一篇:先谈硬件 1. 先明确讨论范围 这个系列只讨论: 单机、单进程内部的并发。 也就是说,我们关注的是同一个进程中的多个执行单元。 例如: Java Thread / Virtual Thread; Go Goroutine; Python Thread / asyncio Task。 不讨论跨进程通信、分布式系统和网络通信。 2. 从一个共享变量开始 假设进程中有一个变量: [代码示例略] 现在有两个执行单元: [代码示例略] 如果 A 和 B 各执行一次,最终结果是否一定是: [代码示例略] 答案是不一定。 因为 count++ 可以从逻辑上拆成三个步骤: [代码示例略] 于是可能出现: [代码示例略] 最终: [代码示例略] 两个线程都完成了一次 +1 ,但因为它们读取到了相同的旧值 0 ,最终两次计算结果都只是 1 ,其中一次更新被覆盖了。

目录 1. 先明确讨论范围 2. 从一个共享变量开始 3. 两种主要的协作模型 3.1 Shared Memory:通过同步保护共享状态 3.2 Message Passing:通过消息进行协作 4. 为什么这些代码能够正确工作? 5. 语言需要定义并发语义 6. 为什么还要继续下钻到硬件? 7. 下一篇:先谈硬件 1. 先明确讨论范围 这个系列只讨论: 单机、单进程内部的并发。 也就是说,我们关注的是同一个进程中的多个执行单元。 例如: Java Thread / Virtual Thread; Go Goroutine; Python Thread / asyncio Task。 不讨论跨进程通信、分布式系统和网络通信。 2. 从一个共享变量开始 假设进程中有一个变量: [代码示例略] 现在有两个执行单元: [代码示例略] 如果 A 和 B 各执行一次,最终结果是否一定是: [代码示例略] 答案是不一定。 因为 count++ 可以从逻辑上拆成三个步骤: [代码示例略] 于是可能出现: [代码示例略] 最终: [代码示例略] 两个线程都完成了一次 +1 ,但因为它们读取到了相同的旧值 0 ,最终两次计算结果都只是 1 ,其中一次更新被覆盖了。 问题的关键在于两个Thread同时修改了 counter ,也就是 多个执行单元同时访问并修改了同一份状态。

目录 1. 先明确讨论范围 2. 从一个共享变量开始 3. 两种主要的协作模型 3.1 Shared Memory:通过同步保护共享状态 3.2 Message Passing:通过消息进行协作 4. 为什么这些代码能够正确工作? 5. 语言需要定义并发语义 6. 为什么还要继续下钻到硬件? 7. 下一篇:先谈硬件 1. 先明确讨论范围 这个系列只讨论: 单机、单进程内部的并发。 也就是说,我们关注的是同一个进程中的多个执行单元。 例如: Java Thread / Virtual Thread; Go Goroutine; Python Thread / asyncio Task。 不讨论跨进程通信、分布式系统和网络通信。 2. 从一个共享变量开始 假设进程中有一个变量: [代码示例略] 现在有两个执行单元: [代码示例略] 如果 A 和 B 各执行一次,最终结果是否一定是: [代码示例略] 答案是不一定。 因为 count++ 可以从逻辑上拆成三个步骤: [代码示例略] 于是可能出现: [代码示例略] 最终: [代码示例略] 两个线程都完成了一次 +1 ,但因为它们读取到了相同的旧值 0 ,最终两次计算结果都只是 1 ,其中一次更新被覆盖了。 问题的关键在于两个Thread同时修改了 counter ,也就是 多个执行单元同时访问并修改了同一份状态。 在单机、单进程范围内,当多个执行单元需要共享数据时,主要通过两种模型协作: Shared Memory / Shared State :多个执行单元直接访问同一份状态; Message Passing :执行单元之间通过消息交换信息。

目录 1. 先明确讨论范围 2. 从一个共享变量开始 3. 两种主要的协作模型 3.1 Shared Memory:通过同步保护共享状态 3.2 Message Passing:通过消息进行协作 4. 为什么这些代码能够正确工作? 5. 语言需要定义并发语义 6. 为什么还要继续下钻到硬件? 7. 下一篇:先谈硬件 1. 先明确讨论范围 这个系列只讨论: 单机、单进程内部的并发。 也就是说,我们关注的是同一个进程中的多个执行单元。 例如: Java Thread / Virtual Thread; Go Goroutine; Python Thread / asyncio Task。 不讨论跨进程通信、分布式系统和网络通信。 2. 从一个共享变量开始 假设进程中有一个变量: [代码示例略] 现在有两个执行单元: [代码示例略] 如果 A 和 B 各执行一次,最终结果是否一定是: [代码示例略] 答案是不一定。 因为 count++ 可以从逻辑上拆成三个步骤: [代码示例略] 于是可能出现: [代码示例略] 最终: [代码示例略] 两个线程都完成了一次 +1 ,但因为它们读取到了相同的旧值 0 ,最终两次计算结果都只是 1 ,其中一次更新被覆盖了。 问题的关键在于两个Thread同时修改了 counter ,也就是 多个执行单元同时访问并修改了同一份状态。 在单机、单进程范围内,当多个执行单元需要共享数据时,主要通过两种模型协作: Shared Memory / Shared State :多个执行单元直接访问同一份状态; Message Passing :执行单元之间通过消息交换信息。 下面仍然以 count++ 为例,看这两种模型分别如何处理前面的并发问题。

行动建议:收藏这篇,下次碰到同类问题先翻出来对照做一遍。好经验的价值,在于用起来。你最近被这类问题卡过吗? 来源|博客园《并发编程(零):并发问题与讨论范围》,https://www.cnblogs.com/ThinkerQAQ/p/22954074.html

程序员技术场技术后端

评论(0)

暂无评论,来抢第一条。