什么是多线程程序,它是如何工作的?
What is a multithreading program and how does it work?
什么是多线程程序,它是如何工作的?我读了一些文件,但我很困惑。我知道代码是逐行执行的,但我不明白程序是如何管理的。
一个简单的答案是 appreciated.c# 请举个例子(只有动画!)
在厨房里可以找到一个简单的类比。
您之前可能已经使用食谱烹饪过 -- 从指定的配料开始,按照食谱中指示的步骤进行操作,最后(希望)您可以享用美味的菜肴。如果你这样做,那么你已经执行了一个传统(非多线程)程序。
但是,如果您必须做一顿包含许多不同菜肴的全餐怎么办?简单的方法是从第一个菜谱开始,按照菜谱上的所有内容进行操作,完成后,将完成的菜肴(和第一个菜谱)放在一边,然后从第二个菜谱开始,按照菜谱中的所有内容进行操作,将第二道菜(和第二道菜)放在一边,依此类推,直到您一个接一个地完成所有菜谱。这会奏效,但您最终可能会在厨房里待上 10 个小时,当然,当最后一道菜准备好食用时,第一道菜可能已经凉了,让人倒胃口。
因此,您可能会做大多数厨师所做的事情,即同时开始制作多个食谱。例如,您可以将烤肉放入烤箱烘烤 45 分钟,但与其坐在烤箱前等待 45 分钟让烤肉烤熟,不如将这 45 分钟花在切菜上。当烤箱定时器响起时,你放下菜刀,把烤好的烤肉从烤箱里拿出来让它冷却,然后继续切菜,等等。如果你能做到这一点,那么你就成功地同时处理了几个 recipes/programs。也就是说,您并不是真的同时处理多个食谱(您仍然只有两只手!),而是在必要时从遵循一个食谱到遵循另一个食谱来回跳转,从而在多个任务上取得进展,而不是经常摆弄你的拇指。做得好,你可以在更短的时间内准备好整顿饭,而且几乎同时所有的东西都会又热又新鲜。如果你这样做,你正在执行一个简单的多线程程序。
那如果你想真的花哨,你可以雇几个其他厨师和你同时在厨房工作,这样你就可以得到更多在一定时间内准备好的食物。如果这样做,您的团队就是在进行 多重处理 ,每个厨师都承担全部工作的一部分,并且所有厨师都同时工作。请注意,如前一段所述,每个厨师很可能正在处理多个食谱(即多任务处理)。
至于计算机如何做这种事情(不再类比厨师),它通常使用现成的运行列表来实现它线程和定时器。当计时器关闭时(或者当当前正在执行的线程暂时无事可做时,例如因为它正在等待从慢速硬盘驱动器或其他东西加载数据),操作系统会执行 context switch,其中暂停当前线程(通过将其放入某处的列表并且不再执行来自该线程代码的指令),然后从列表中拉出另一个准备就绪的运行线程ready-to-运行 线程并开始执行来自该线程代码的指令。只要有必要,这种情况就会重复,通常每隔几毫秒就会发生一次上下文切换,给人一种错觉,即使在单核 CPU 上,多个程序也在 运行ning "at the same time"。 (在多核 CPU 上,它在每个核上做同样的事情,在那种情况下,它不再只是一种幻觉;多个程序真的 是 运行同时宁)
What is a multi-threading program and how does it work exactly?
关于这个问题有趣的部分是关于这个主题的整本书都是写的,但很多人仍然难以捉摸。我将尝试按照下面详述的顺序进行解释。
请注意,这只是为了提供一个要点,这样的答案永远无法充分体现所需的深度和细节。关于视频,我遇到的最好的是付费订阅的一部分(Wintellect 和 Pluralsight),如果您还没有订阅,请查看是否可以试听:
Wintellect by Jeffery Ritcher(来自他的书,通过 C# 的 CLR,与线程基础知识有相同的章节)
解释顺序
- 什么是线程?
- 为什么引入线程,主要目的是什么?
- 陷阱以及如何使用同步构造避免它们?
- 线程与线程池?
- 多线程编程的演变API,如并行API、任务API
- 并发集合,使用情况?
- Async-Await,有线程但没有线程,为什么它们最适合IO
What is a thread ?
它是软件实现,纯粹是一个 Windows OS 概念 (multi-threaded architecture)
,它是最小的工作单元。 windows OS 上的每个进程至少有一个线程,每个方法调用都在线程上完成。每个进程可以有多个线程,并行地做多件事(前提是硬件支持)。
其他基于 Unix
的 OS 是多进程架构,事实上在 Windows 中,即使是像 Oracle.exe
这样最复杂的软件也有单进程和多线程用于不同的关键后台操作.
Why were threads introduced, main purpose ?
与并发是主要目的的看法相反,是稳健性导致线程的引入,想象一下 Windows 上的每个进程 运行 使用相同的线程(在最初的 16位版本)和其中一个进程崩溃,在大多数情况下这仅仅意味着系统重启以恢复。将线程用于并发操作,因为可以在每个进程中调用多个线程,这很明显。事实上,充分利用多核处理器甚至很重要。
Pitfalls and how to avoid using Synchronization constructs ?
更多的线程意味着更多的工作同时完成,但问题来了,当访问相同的内存时,尤其是对于 Write
,因为这会导致:
- 内存损坏
- 竞争条件
另外,还有一个问题就是线程是非常耗费资源的,每个线程都有一个线程环境块,内核内存分配。此外,为了在处理器内核上调度每个线程,时间会花费在上下文切换上。滥用可能会导致巨大的性能损失,而不是改进。
为避免与线程相关的损坏问题,使用同步结构很重要,例如根据需要使用 lock, mutex, semaphore,
。读取始终是线程安全的,但写入需要适当的同步。
Thread Vs ThreadPool ?
真正的线程不是那些,我们在 C#.Net 中使用,那只是调用 Win32 线程的托管包装器。挑战仍然存在于用户严重滥用的能力上,比如调用超过所需数量的线程,分配处理器亲和力,所以我们请求一个标准池来排队工作项及其 windows 不是更好吗?何时需要新线程,何时已有线程可以安排工作项。线程是一种昂贵的资源,需要在使用上进行优化,否则就是祸不单行。
Evolution of Multi threaded programming, like Parallel API, Task API
从 .Net 4.0 开始,各种新的 APIs Parallel.For,Parallel.For 各自用于数据并行化和任务并行化,使得在系统中引入并发变得非常简单.这些 API 再次在内部使用线程池工作。任务更像是在未来某个时间安排工作。现在引入并发就像轻而易举,尽管仍然需要同步结构来避免内存损坏,可以使用竞争条件或线程安全集合。
Concurrent Collections, usage ?
像 ConcurrentBag, ConcurrentQueue, ConcurrentDictionary
这样的实现,System.Collections.Concurrent
的一部分是固有线程安全的,使用 spin-wait
并且比显式 Synchronization
更容易和更快。也更容易管理和工作。还有另一组 API,如 ImmutableList
System.Collections.Immutable
,可通过 nuget 获得,它们是线程安全的,因为在内部创建了另一个数据结构副本。
Async-Await, thread but no thread, why they are best for IO
这是并发的一个重要方面,用于 IO
调用(磁盘、网络),到目前为止讨论的其他 APIs,用于基于计算的并发,因此线程很重要并使之成为可能更快,但是对于 IO 调用线程除了等待调用 return 没有用处,IO 调用在基于硬件的队列 IO Completion ports
上处理
为什么不参考 Microsoft 自己的 .net 文档classSystem.Threading.Thread?
它有一些用 C# 编写的简单示例程序(在页面底部),正如您所要求的:
其实多线程就是同时做多个进程在一起。您可以并行完成流程。
其实多线程就是同时做多个进程在一起。您可以并行完成流程。您可以从主线程中获取任务,然后以其他方式执行并完成。
什么是多线程程序,它是如何工作的?我读了一些文件,但我很困惑。我知道代码是逐行执行的,但我不明白程序是如何管理的。
一个简单的答案是 appreciated.c# 请举个例子(只有动画!)
在厨房里可以找到一个简单的类比。
您之前可能已经使用食谱烹饪过 -- 从指定的配料开始,按照食谱中指示的步骤进行操作,最后(希望)您可以享用美味的菜肴。如果你这样做,那么你已经执行了一个传统(非多线程)程序。
但是,如果您必须做一顿包含许多不同菜肴的全餐怎么办?简单的方法是从第一个菜谱开始,按照菜谱上的所有内容进行操作,完成后,将完成的菜肴(和第一个菜谱)放在一边,然后从第二个菜谱开始,按照菜谱中的所有内容进行操作,将第二道菜(和第二道菜)放在一边,依此类推,直到您一个接一个地完成所有菜谱。这会奏效,但您最终可能会在厨房里待上 10 个小时,当然,当最后一道菜准备好食用时,第一道菜可能已经凉了,让人倒胃口。
因此,您可能会做大多数厨师所做的事情,即同时开始制作多个食谱。例如,您可以将烤肉放入烤箱烘烤 45 分钟,但与其坐在烤箱前等待 45 分钟让烤肉烤熟,不如将这 45 分钟花在切菜上。当烤箱定时器响起时,你放下菜刀,把烤好的烤肉从烤箱里拿出来让它冷却,然后继续切菜,等等。如果你能做到这一点,那么你就成功地同时处理了几个 recipes/programs。也就是说,您并不是真的同时处理多个食谱(您仍然只有两只手!),而是在必要时从遵循一个食谱到遵循另一个食谱来回跳转,从而在多个任务上取得进展,而不是经常摆弄你的拇指。做得好,你可以在更短的时间内准备好整顿饭,而且几乎同时所有的东西都会又热又新鲜。如果你这样做,你正在执行一个简单的多线程程序。
那如果你想真的花哨,你可以雇几个其他厨师和你同时在厨房工作,这样你就可以得到更多在一定时间内准备好的食物。如果这样做,您的团队就是在进行 多重处理 ,每个厨师都承担全部工作的一部分,并且所有厨师都同时工作。请注意,如前一段所述,每个厨师很可能正在处理多个食谱(即多任务处理)。
至于计算机如何做这种事情(不再类比厨师),它通常使用现成的运行列表来实现它线程和定时器。当计时器关闭时(或者当当前正在执行的线程暂时无事可做时,例如因为它正在等待从慢速硬盘驱动器或其他东西加载数据),操作系统会执行 context switch,其中暂停当前线程(通过将其放入某处的列表并且不再执行来自该线程代码的指令),然后从列表中拉出另一个准备就绪的运行线程ready-to-运行 线程并开始执行来自该线程代码的指令。只要有必要,这种情况就会重复,通常每隔几毫秒就会发生一次上下文切换,给人一种错觉,即使在单核 CPU 上,多个程序也在 运行ning "at the same time"。 (在多核 CPU 上,它在每个核上做同样的事情,在那种情况下,它不再只是一种幻觉;多个程序真的 是 运行同时宁)
What is a multi-threading program and how does it work exactly?
关于这个问题有趣的部分是关于这个主题的整本书都是写的,但很多人仍然难以捉摸。我将尝试按照下面详述的顺序进行解释。
请注意,这只是为了提供一个要点,这样的答案永远无法充分体现所需的深度和细节。关于视频,我遇到的最好的是付费订阅的一部分(Wintellect 和 Pluralsight),如果您还没有订阅,请查看是否可以试听:
Wintellect by Jeffery Ritcher(来自他的书,通过 C# 的 CLR,与线程基础知识有相同的章节)
解释顺序
- 什么是线程?
- 为什么引入线程,主要目的是什么?
- 陷阱以及如何使用同步构造避免它们?
- 线程与线程池?
- 多线程编程的演变API,如并行API、任务API
- 并发集合,使用情况?
- Async-Await,有线程但没有线程,为什么它们最适合IO
What is a thread ?
它是软件实现,纯粹是一个 Windows OS 概念 (multi-threaded architecture)
,它是最小的工作单元。 windows OS 上的每个进程至少有一个线程,每个方法调用都在线程上完成。每个进程可以有多个线程,并行地做多件事(前提是硬件支持)。
其他基于 Unix
的 OS 是多进程架构,事实上在 Windows 中,即使是像 Oracle.exe
这样最复杂的软件也有单进程和多线程用于不同的关键后台操作.
Why were threads introduced, main purpose ?
与并发是主要目的的看法相反,是稳健性导致线程的引入,想象一下 Windows 上的每个进程 运行 使用相同的线程(在最初的 16位版本)和其中一个进程崩溃,在大多数情况下这仅仅意味着系统重启以恢复。将线程用于并发操作,因为可以在每个进程中调用多个线程,这很明显。事实上,充分利用多核处理器甚至很重要。
Pitfalls and how to avoid using Synchronization constructs ?
更多的线程意味着更多的工作同时完成,但问题来了,当访问相同的内存时,尤其是对于 Write
,因为这会导致:
- 内存损坏
- 竞争条件
另外,还有一个问题就是线程是非常耗费资源的,每个线程都有一个线程环境块,内核内存分配。此外,为了在处理器内核上调度每个线程,时间会花费在上下文切换上。滥用可能会导致巨大的性能损失,而不是改进。
为避免与线程相关的损坏问题,使用同步结构很重要,例如根据需要使用 lock, mutex, semaphore,
。读取始终是线程安全的,但写入需要适当的同步。
Thread Vs ThreadPool ?
真正的线程不是那些,我们在 C#.Net 中使用,那只是调用 Win32 线程的托管包装器。挑战仍然存在于用户严重滥用的能力上,比如调用超过所需数量的线程,分配处理器亲和力,所以我们请求一个标准池来排队工作项及其 windows 不是更好吗?何时需要新线程,何时已有线程可以安排工作项。线程是一种昂贵的资源,需要在使用上进行优化,否则就是祸不单行。
Evolution of Multi threaded programming, like Parallel API, Task API
从 .Net 4.0 开始,各种新的 APIs Parallel.For,Parallel.For 各自用于数据并行化和任务并行化,使得在系统中引入并发变得非常简单.这些 API 再次在内部使用线程池工作。任务更像是在未来某个时间安排工作。现在引入并发就像轻而易举,尽管仍然需要同步结构来避免内存损坏,可以使用竞争条件或线程安全集合。
Concurrent Collections, usage ?
像 ConcurrentBag, ConcurrentQueue, ConcurrentDictionary
这样的实现,System.Collections.Concurrent
的一部分是固有线程安全的,使用 spin-wait
并且比显式 Synchronization
更容易和更快。也更容易管理和工作。还有另一组 API,如 ImmutableList
System.Collections.Immutable
,可通过 nuget 获得,它们是线程安全的,因为在内部创建了另一个数据结构副本。
Async-Await, thread but no thread, why they are best for IO
这是并发的一个重要方面,用于 IO
调用(磁盘、网络),到目前为止讨论的其他 APIs,用于基于计算的并发,因此线程很重要并使之成为可能更快,但是对于 IO 调用线程除了等待调用 return 没有用处,IO 调用在基于硬件的队列 IO Completion ports
为什么不参考 Microsoft 自己的 .net 文档classSystem.Threading.Thread?
它有一些用 C# 编写的简单示例程序(在页面底部),正如您所要求的:
其实多线程就是同时做多个进程在一起。您可以并行完成流程。
其实多线程就是同时做多个进程在一起。您可以并行完成流程。您可以从主线程中获取任务,然后以其他方式执行并完成。