关于启动大型多线程编程项目的建议
我的公司目前运行一个第三方模拟程序(自然灾害风险建模),该程序从磁盘中吸收千兆字节的数据,然后处理几天以产生结果。我很快就会被要求将其重写为多线程应用程序,以便它在几小时而不是几天内运行。我预计需要大约 6 个月的时间来完成转换,并将单独工作。
我们有一个 24 进程的盒子来运行这个。我将可以访问原始程序的源代码(我认为是用 C++ 编写的),但目前我对它的设计方式知之甚少。
我需要关于如何解决这个问题的建议。我是一位经验丰富的程序员(约 30 年,目前使用 C# 3.5),但没有多处理器/多线程经验。如果合适的话,我愿意并且渴望学习一门新语言。我正在寻找有关语言、学习资源、书籍、架构指南的建议。 。
要求:Windows操作系统 商业级编译器,提供大量支持和良好的学习资源。不需要花哨的 GUI - 它可能会从配置文件运行并将结果放入 SQL Server 数据库中。
编辑:当前的应用程序是 C++,但我几乎肯定不会使用该语言进行重写。我删除了某人添加的 C++ 标签。
My company currently runs a third-party simulation program (natural catastrophe risk modeling) that sucks up gigabytes of data off a disk and then crunches for several days to produce results. I will soon be asked to rewrite this as a multi-threaded app so that it runs in hours instead of days. I expect to have about 6 months to complete the conversion and will be working solo.
We have a 24-proc box to run this. I will have access to the source of the original program (written in C++ I think), but at this point I know very little about how it's designed.
I need advice on how to tackle this. I'm an experienced programmer (~ 30 years, currently working in C# 3.5) but have no multi-processor/multi-threaded experience. I'm willing and eager to learn a new language if appropriate. I'm looking for recommendations on languages, learning resources, books, architectural guidelines. etc.
Requirements: Windows OS. A commercial grade compiler with lots of support and good learning resources available. There is no need for a fancy GUI - it will probably run from a config file and put results into a SQL Server database.
Edit: The current app is C++ but I will almost certainly not be using that language for the re-write. I removed the C++ tag that someone added.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
数值过程模拟通常在单个离散问题网格上运行(例如,地球表面或气体和尘埃云 ),这通常排除简单的任务耕种或并发方法。这是因为划分在表示物理空间区域的一组处理器上的网格不是一组独立的任务。每个子网格边缘的网格单元需要根据存储在逻辑空间中相邻的其他处理器上的网格单元的值进行更新。
在高性能计算中,模拟通常是使用 并行化 MPI 或 OpenMP。 MPI 是一个消息传递库,具有多种语言的绑定,包括 C、C++、Fortran、Python 和 C#。 OpenMP 是一个用于共享内存多处理的 API。一般来说,MPI 比 OpenMP 更难编码,更具侵入性,但也更灵活。 OpenMP 需要在处理器之间共享内存区域,因此不适合许多架构。 混合方案也是可能的。
这种类型的编程有其特殊的挑战。以及竞赛条件、死锁,活锁 >,以及并发编程的所有其他乐趣,您需要考虑处理器网格的拓扑 - 您选择如何在物理处理器之间分割逻辑网格。这很重要,因为并行加速是处理器之间通信量的函数,这本身是分解网格的总边长的函数。随着您添加更多处理器,此表面积会增加,从而增加通信开销。增加粒度最终会变得令人望而却步。
另一个重要的考虑因素是可以并行化的代码比例。然后,阿姆达尔定律规定了理论上可达到的最大加速比。在开始编写任何代码之前,您应该能够对此进行估计。
这两个事实将共同限制您可以运行的处理器的最大数量。最佳位置可能比您想象的要低得多。
我推荐这本书高性能计算,如果你能拿到的话。特别是关于性能基准测试和调优的章节是无价的。
劳伦斯利弗莫尔国家实验室< /a>.
Numerical process simulations are typically run over a single discretised problem grid (for example, the surface of the Earth or clouds of gas and dust), which usually rules out simple task farming or concurrency approaches. This is because a grid divided over a set of processors representing an area of physical space is not a set of independent tasks. The grid cells at the edge of each subgrid need to be updated based on the values of grid cells stored on other processors, which are adjacent in logical space.
In high-performance computing, simulations are typically parallelised using either MPI or OpenMP. MPI is a message passing library with bindings for many languages, including C, C++, Fortran, Python, and C#. OpenMP is an API for shared-memory multiprocessing. In general, MPI is more difficult to code than OpenMP, and is much more invasive, but is also much more flexible. OpenMP requires a memory area shared between processors, so is not suited to many architectures. Hybrid schemes are also possible.
This type of programming has its own special challenges. As well as race conditions, deadlocks, livelocks, and all the other joys of concurrent programming, you need to consider the topology of your processor grid - how you choose to split your logical grid across your physical processors. This is important because your parallel speedup is a function of the amount of communication between your processors, which itself is a function of the total edge length of your decomposed grid. As you add more processors, this surface area increases, increasing the amount of communication overhead. Increasing the granularity will eventually become prohibitive.
The other important consideration is the proportion of the code which can be parallelised. Amdahl's law then dictates the maximum theoretically attainable speedup. You should be able to estimate this before you start writing any code.
Both of these facts will conspire to limit the maximum number of processors you can run on. The sweet spot may be considerably lower than you think.
I recommend the book High Performance Computing, if you can get hold of it. In particular, the chapter on performance benchmarking and tuning is priceless.
An excellent online overview of parallel computing, which covers the major issues, is this introduction from Lawerence Livermore National Laboratory.
多线程项目中最大的问题是跨线程可见太多状态 - 编写以不安全的方式读取/改变数据的代码太容易了,特别是在存在缓存一致性、弱一致内存等问题的多处理器环境中可能会发挥作用。
调试竞争条件显然是令人不愉快的。
比如说,您正在考虑将工作分布在网络上的多台机器上:也就是说,确定哪些任务可以并行发生,每个任务的输入是什么,每个任务的输出是什么,以及在给定任务开始之前必须完成哪些任务。练习的目的是确保仔细考虑数据对另一个线程可见的每个位置以及生成新线程的每个位置。
一旦这样的初始设计完成,数据所有权就会有明确的划分,并且所有权的取得/转移也会有明确的点;因此,您将处于一个非常有利的位置,可以安全地利用多线程为您提供的可能性 - 廉价的共享数据、廉价的同步、无锁共享数据结构。
Your biggest problem in a multithreaded project is that too much state is visible across threads - it is too easy to write code that reads / mutates data in an unsafe manner, especially in a multiprocessor environment where issues such as cache coherency, weakly consistent memory etc might come into play.
Debugging race conditions is distinctly unpleasant.
Approach your design as you would if, say, you were considering distributing your work across multiple machines on a network: that is, identify what tasks can happen in parallel, what the inputs to each task are, what the outputs of each task are, and what tasks must complete before a given task can begin. The point of the exercise is to ensure that each place where data becomes visible to another thread, and each place where a new thread is spawned, are carefully considered.
Once such an initial design is complete, there will be a clear division of ownership of data, and clear points at which ownership is taken / transferred; and so you will be in a very good position to take advantage of the possibilities that multithreading offers you - cheaply shared data, cheap synchronisation, lockless shared data structures - safely.
如果您可以将工作负载拆分为不相关的工作块(即数据集可以按位处理,没有大量的数据依赖性),那么我会使用线程池/任务机制。大概 C# 具有与 Java 的 java.util.concurrent 等效的功能。我将从数据创建工作单元,并将它们包装在任务中,然后将任务扔到线程池中。
当然,性能在这里可能是必要的。如果您可以按原样保留原始处理代码内核,那么您可以从 C# 应用程序中调用它。
如果代码具有大量数据依赖性,则分解为线程任务可能会困难得多,但您可以将其分解为操作管道。这意味着线程 1 将数据传递到线程 2,线程 2 将数据传递到线程 3 到 8,线程 3 到 8 将数据传递到线程 9,等等。
如果代码包含大量浮点数学,则可能值得考虑使用 OpenCL 或 CUDA 进行重写,并在 GPU 而不是 CPU 上运行。
If you can split the workload up into non-dependent chunks of work (i.e., the data set can be processed in bits, there aren't lots of data dependencies), then I'd use a thread pool / task mechanism. Presumably whatever C# has as an equivalent to Java's java.util.concurrent. I'd create work units from the data, and wrap them in a task, and then throw the tasks at the thread pool.
Of course performance might be a necessity here. If you can keep the original processing code kernel as-is, then you can call it from within your C# application.
If the code has lots of data dependencies, it may be a lot harder to break up into threaded tasks, but you might be able to break it up into a pipeline of actions. This means thread 1 passes data to thread 2, which passes data to threads 3 through 8, which pass data onto thread 9, etc.
If the code has a lot of floating point mathematics, it might be worth looking at rewriting in OpenCL or CUDA, and running it on GPUs instead of CPUs.
对于一个为期 6 个月的项目,我想说,首先开始阅读一本关于该主题的好书绝对是值得的。我建议您阅读Joe Duffy 的 Windows 并发编程。这是我所知道的有关该主题的最详尽的书,它涵盖了 .NET 和本机 Win32 线程。当我发现这个宝石时,我已经编写多线程程序 10 年了,并且几乎在每一章中仍然发现了我不知道的东西。
此外,“自然灾害风险建模”听起来像是很多数学知识。也许您应该看看英特尔的 IPP 库:它提供了许多常见的低级数学和信号处理算法的原语。它支持开箱即用的多线程,这可能使您的任务变得更加容易。
For a 6 month project I'd say it definitely pays out to start reading a good book about the subject first. I would suggest Joe Duffy's Concurrent Programming on Windows. It's the most thorough book I know about the subject and it covers both .NET and native Win32 threading. I've written multithreaded programs for 10 years when I discovered this gem and still found things I didn't know in almost every chapter.
Also, "natural catastrophe risk modeling" sounds like a lot of math. Maybe you should have a look at Intel's IPP library: it provides primitives for many common low-level math and signal processing algorithms. It supports multi threading out of the box, which may make your task significantly easier.
如果您为其设计项目,则可以使用许多技术来处理多线程。
最普遍和普遍的就是“避免共享状态”。只要有可能,就在线程之间复制资源,而不是让它们访问相同的共享副本。
如果您自己编写低级同步代码,则必须记住绝对不要做出任何假设。编译器和 CPU 都可能对代码进行重新排序,从而产生竞争条件或死锁,而在阅读代码时,这些情况似乎不可能发生。防止这种情况的唯一方法是使用内存屏障。请记住,即使是最简单的操作也可能会遇到线程问题。像
++i
这样简单的东西通常不是原子的,如果多个线程访问i
,您将得到不可预测的结果。当然,仅仅因为您为变量分配了值,并不能保证新值对其他线程可见。编译器可能会推迟将其实际写入内存。同样,内存屏障迫使它“刷新”所有挂起的内存 I/O。
如果我是你,如果可能的话,我会选择比简单的锁/互斥体/监视器/关键部分更高级别的同步模型。有一些 CSP 库可用于大多数语言和平台,包括 .NET 语言和本机 C++ 。
这通常使得竞争条件和死锁的检测和修复变得微不足道,并且允许令人难以置信的可扩展性。但这种范例也存在一定量的开销,因此每个线程完成的工作可能比其他技术少。它还需要专门针对此范例构建整个应用程序(因此对现有代码进行改造很棘手,但由于您是从头开始,所以这不是什么问题 - 但您仍然会感到陌生
)方法可能是事务内存。这更容易适应传统的程序结构,但也有一些限制,而且我不知道有多少生产质量的库(STM.NET 最近发布,可能值得一试。Intel 有一个 C++ 但无论
您使用哪种方法,您都必须仔细考虑如何将工作分解为独立的任务,以及如何避免线程之间的串扰。任何时候两个线程访问同一个变量,都会有潜在的错误。任何时候两个线程访问同一个变量或同一地址附近的另一个变量(例如数组中的下一个或上一个元素),数据都必须在内核之间交换,迫使它从CPU缓存刷新到内存,然后读入另一个核心的缓存。这可能会对性能造成重大影响。
哦,如果您确实用 C++ 编写应用程序,请不要低估这种语言。在能够编写健壮的代码之前,您必须详细学习该语言,更不用说健壮的线程代码了。
There are a lot of techniques that can be used to deal with multithreading if you design the project for it.
The most general and universal is simply "avoid shared state". Whenever possible, copy resources between threads, rather than making them access the same shared copy.
If you're writing the low-level synchronization code yourself, you have to remember to make absolutely no assumptions. Both the compiler and CPU may reorder your code, creating race conditions or deadlocks where none would seem possible when reading the code. The only way to prevent this is with memory barriers. And remember that even the simplest operation may be subject to threading issues. Something as simple as
++i
is typically not atomic, and if multiple threads accessi
, you'll get unpredictable results.And of course, just because you've assigned a value to a variable, that's no guarantee that the new value will be visible to other threads. The compiler may defer actually writing it out to memory. Again, a memory barrier forces it to "flush" all pending memory I/O.
If I were you, I'd go with a higher level synchronization model than simple locks/mutexes/monitors/critical sections if possible. There are a few CSP libraries available for most languages and platforms, including .NET languages and native C++.
This usually makes race conditions and deadlocks trivial to detect and fix, and allows a ridiculous level of scalability. But there's a certain amount of overhead associated with this paradigm as well, so each thread might get less work done than it would with other techniques. It also requires the entire application to be structured specifically for this paradigm (so it's tricky to retrofit onto existing code, but since you're starting from scratch, it's less of an issue -- but it'll still be unfamiliar to you)
Another approach might be Transactional Memory. This is easier to fit into a traditional program structure, but also has some limitations, and I don't know of many production-quality libraries for it (STM.NET was recently released, and may be worth checking out. Intel has a C++ compiler with STM extensions built into the language as well)
But whichever approach you use, you'll have to think carefully about how to split the work up into independent tasks, and how to avoid cross-talk between threads. Any time two threads access the same variable, you have a potential bug. And any time two threads access the same variable or just another variable near the same address (for example, the next or previous element in an array), data will have to be exchanged between cores, forcing it to be flushed from CPU cache to memory, and then read into the other core's cache. Which can be a major performance hit.
Oh, and if you do write the application in C++, don't underestimate the language. You'll have to learn the language in detail before you'll be able to write robust code, much less robust threaded code.
在这种情况下,我们所做的一件非常有效的事情就是将要完成的工作分解为单独的块,并将每个块上的操作分解为不同的处理器。然后我们就有了处理器链,数据块可以独立地通过这些链工作。链中的每组处理器都可以在多个线程上运行,并且可以根据其自身相对于链中其他处理器的性能来处理更多或更少的数据。
此外,将数据和操作分解为更小的部分,使应用程序更易于维护和测试。
One thing we've done in this situation that has worked really well for us is to break the work to be done into individual chunks and the actions on each chunk into different processors. Then we have chains of processors and data chunks can work through the chains independently. Each set of processors within the chain can run on multiple threads each and can process more or less data depending on their own performance relative to the other processors in the chain.
Also breaking up both the data and actions into smaller pieces makes the app much more maintainable and testable.
这里可以提供很多具体的个人建议,并且已经有几个人这样做了。
然而,没有人能准确地告诉您如何使这一切满足您的特定要求(您甚至还没有完全了解自己),因此我强烈建议您阅读 HPC(高性能计算) 现在可以清晰地了解总体概念,并更好地了解哪个方向最适合您的需求。
There's plenty of specific bits of individual advice that could be given here, and several people have done so already.
However nobody can tell you exactly how to make this all work for your specific requirements (which you don't even fully know yourself yet), so I'd strongly recommend you read up on HPC (High Performance Computing) for now to get the over-arching concepts clear and have a better idea which direction suits your needs the most.
您选择使用的模型将由数据结构决定。您的数据是紧耦合还是松耦合?如果您的模拟数据紧密耦合,那么您将需要考虑 OpenMP 或 MPI(并行计算)。如果您的数据是松散耦合的,那么作业池可能更适合......甚至可能分布式计算方法也可以工作。
我的建议是获取并阅读介绍性文本,以熟悉并发/并行的各种模型。然后查看您的应用程序的需求并决定您需要使用哪种架构。了解您需要哪种架构后,您可以查看可以为您提供帮助的工具。
作为该主题的介绍的一本评价相当高的书是“并发的艺术:线程猴子编写并行应用程序的指南”。
The model you choose to use will be dictated by the structure of your data. Is your data tightly coupled or loosely coupled? If your simulation data is tightly coupled then you'll want to look at OpenMP or MPI (parallel computing). If your data is loosely coupled then a job pool is probably a better fit... possibly even a distributed computing approach could work.
My advice is get and read an introductory text to get familiar with the various models of concurrency/parallelism. Then look at your application's needs and decide which architecture you're going to need to use. After you know which architecture you need, then you can look at tools to assist you.
A fairly highly rated book which works as an introduction to the topic is "The Art of Concurrency: A Thread Monkey's Guide to Writing Parallel Application".
特别了解 Erlang 和“Actor 模型”。如果您使所有数据不可变,那么您将更容易对其进行并行化。
Read about Erlang and the "Actor Model" in particular. If you make all your data immutable, you will have a much easier time parallelizing it.
大多数其他答案都提供了有关项目分区的良好建议 - 寻找可以干净地并行执行且需要很少的数据共享的任务。请注意非线程安全的构造,例如静态或全局变量,或非线程安全的库。我们遇到的最糟糕的一个是 TNT 库,它甚至不允许线程安全在某些情况下读取。
与所有优化一样,首先关注瓶颈,因为线程会增加很多复杂性,您希望在不必要的地方避免它。
您需要很好地掌握各种线程原语(互斥体、信号量、临界区、条件等)以及它们的有用情况。
如果您打算继续使用 C++,我要补充的一件事是,我们使用 boost.thread 库。它提供了大部分所需的多线程原语,尽管缺少线程池(而且我对可以通过谷歌找到的非官方“Boost”线程池持谨慎态度,因为它存在许多死锁问题)。
Most of the other answers offer good advice regarding partitioning the project - look for tasks that can be cleanly executed in parallel with very little data sharing required. Be aware of non-thread safe constructs such as static or global variables, or libraries that are not thread safe. The worst one we've encountered is the TNT library, which doesn't even allow thread-safe reads under some circumstances.
As with all optimisation, concentrate on the bottlenecks first, because threading adds a lot of complexity you want to avoid it where it isn't necessary.
You'll need a good grasp of the various threading primitives (mutexes, semaphores, critical sections, conditions, etc.) and the situations in which they are useful.
One thing I would add, if you're intending to stay with C++, is that we have had a lot of success using the boost.thread library. It supplies most of the required multi-threading primitives, although does lack a thread pool (and I would be wary of the unofficial "boost" thread pool one can locate via google, because it suffers from a number of deadlock issues).
我会考虑在 .NET 4.0 中执行此操作,因为它有很多专门针对使编写并发代码更容易的新支持。它的正式发布日期是 2010 年 3 月 22 日,但在此之前它可能会 RTM,您现在可以开始使用相当稳定的 Beta 2。
您可以使用您更熟悉的 C#,也可以使用托管 C++。
在较高级别上,尝试将程序分解为 System.Threading.Tasks.Task 是单独的工作单元。此外,我会尽量减少共享状态的使用,并考虑使用 Parallel.For(或 ForEach )和/或 PLINQ 尽可能。
如果您这样做,将以非常有效的方式为您完成许多繁重的工作。这是微软将越来越支持的方向。
2:我会考虑这样做.NET 4.0,因为它有很多新的支持,专门针对使编写并发代码更容易。它的正式发布日期是 2010 年 3 月 22 日,但在此之前它可能会 RTM,您现在可以开始使用相当稳定的 Beta 2。在较高级别上,尝试将程序分解为 System.Threading.Tasks.Task 是单独的工作单元。此外,我会尽量减少共享状态的使用,并在可能的情况下考虑使用 Parallel.For 和/或 PLINQ。如果您这样做,将以非常有效的方式为您完成许多繁重的工作。 1:http://msdn.microsoft.com/en-us/library/dd321424% 28VS.100%29.aspx
I would consider doing this in .NET 4.0 since it has a lot of new support specifically targeted at making writing concurrent code easier. Its official release date is March 22, 2010, but it will probably RTM before then and you can start with the reasonably stable Beta 2 now.
You can either use C# that you're more familiar with or you can use managed C++.
At a high level, try to break up the program into System.Threading.Tasks.Task's which are individual units of work. In addition, I'd minimize use of shared state and consider using Parallel.For (or ForEach) and/or PLINQ where possible.
If you do this, a lot of the heavy lifting will be done for you in a very efficient way. It's the direction that Microsoft is going to increasingly support.
2: I would consider doing this in .NET 4.0 since it has a lot of new support specifically targeted at making writing concurrent code easier. Its official release date is March 22, 2010, but it will probably RTM before then and you can start with the reasonably stable Beta 2 now. At a high level, try to break up the program into System.Threading.Tasks.Task's which are individual units of work. In addition, I'd minimize use of shared state and consider using Parallel.For and/or PLINQ where possible. If you do this, a lot of the heavy lifting will be done for you in a very efficient way. 1: http://msdn.microsoft.com/en-us/library/dd321424%28VS.100%29.aspx
抱歉,我只是想在这里添加一个悲观或更现实的答案。
你面临时间压力。 6 个月的期限,你甚至不知道这个系统是什么语言、它做什么以及它是如何组织的。如果这不是一个微不足道的计算,那么这就是一个非常糟糕的开始。
最重要的是:你说你以前从未做过多线程编程。这是我同时响起 4 个闹钟的地方。多线程很困难,当你想要正确地做它时,需要很长时间来学习它 - 当你想要赢得巨大的速度提升时,你需要正确地做它。即使使用 Total Views 调试器或 Intel VTune 等优秀工具,调试也非常困难。
然后你说你想用另一种语言重写应用程序 - 好吧,这还没有那么糟糕,因为无论如何你都必须重写它。在不完全重新设计的情况下将单线程程序转变为运行良好的多线程程序的机会几乎为零。
但是,在 3 个月的时间内学习多线程和一门新语言(你的 C++ 技能是什么?)(你必须编写一个废弃的原型 - 所以我将时间跨度切成两半)是极具挑战性的。
我在这里的建议很简单,但我不会喜欢它:现在学习多线程 - 因为它是未来所需的技能 - 但将这项工作留给已经有经验的人。好吧,除非您不关心该计划是否成功,而只是寻求 6 个月的付款。
Sorry i just want to add a pessimistic or better realistic answer here.
You are under time pressure. 6 month deadline and you don't even know for sure what language is this system and what it does and how it is organized. If it is not a trivial calculation then it is a very bad start.
Most importantly: You say you have never done mulitithreading programming before. This is where i get 4 alarm clocks ringing at once. Multithreading is difficult and takes a long time to learn it when you want to do it right - and you need to do it right when you want to win a huge speed increase. Debugging is extremely nasty even with good tools like Total Views debugger or Intels VTune.
Then you say you want to rewrite the app in another lanugage - well this isn't as bad as you have to rewrite it anyway. THe chance to turn a single threaded Program into a well working multithreaded one without total redesign is almost zero.
But learning multithreading and a new language (what is your C++ skills?) with a timeline of 3 month (you have to write a throw away prototype - so i cut the timespan into two halfs) is extremely challenging.
My advise here is simple and will not like it: Learn multithreadings now - because it is a required skill set in the future - but leave this job to someone who already has experience. Well unless you don't care about the program being successfull and are just looking for 6 month payment.
如果可以让所有线程处理不相交的过程数据集,并将其他信息存储在 SQL 数据库中,那么您可以很容易地用 C++ 来实现,并且只需使用 Windows 生成新线程来处理它们自己的部分即可。 API。 SQL 服务器将通过其数据库事务处理所有硬同步魔法!当然,C++ 的执行速度比 C# 快得多。
您绝对应该为此任务修改 C++,并理解 C++ 代码,查找现有代码中的效率错误以及添加多线程功能。
If it's possible to have all the threads working on disjoint sets of process data, and have other information stored in the SQL database, you can quite easily do it in C++, and just spawn off new threads to work on their own parts using the Windows API. The SQL server will handle all the hard synchronization magic with its DB transactions! And of course C++ will perform a lot faster than C#.
You should definitely revise C++ for this task, and understand the C++ code, and look for efficiency bugs in the existing code as well as adding the multi-threaded functionality.
您已将此问题标记为 C++,但提到您目前是 C# 开发人员,因此我不确定您是否会从 C++ 或 C# 处理此作业。无论如何,如果您要使用 C# 或 .NET(包括 C++/CLI):我已为以下 MSDN 文章添加了书签,并且强烈建议您在准备工作中通读它。
异步调用同步方法
You've tagged this question as C++ but mentioned that you're a C# developer currently, so I'm not sure if you'll be tackling this assignment from C++ or C#. Anyway, in case you're going to be using C# or .NET (including C++/CLI): I have the following MSDN article bookmarked and would highly recommend reading through it as part of your prep work.
Calling Synchronous Methods Asynchronously
无论您要使用什么技术来编写本文,请看一下这本关于并发的必读书籍“Concurrent对于 Java 编程” 和 .Net,我强烈推荐 retlang 库并发应用程序。
Whatever technology your going to write this, take a look a this must read book on concurrency "Concurrent programming in Java" and for .Net I highly recommend the retlang library for concurrent app.
我不知道是否已经提到过,但如果我处于您的位置,我现在要做的就是(除了阅读此处发布的每个答案之外)用您最喜欢(最常用)的语言编写一个多线程示例应用程序。
我没有丰富的多线程经验。我过去曾尝试过使用它来娱乐,但我认为通过一次性应用程序获得一些经验将适合您未来的工作。
我祝你在这项工作中好运,我必须承认我希望我有机会从事这样的事情......
I don't know if it was mentioned yet, but if I were in your shoes, what I would be doing right now (aside from reading every answer posted here) is writing a multiple threaded example application in your favorite (most used) language.
I don't have extensive multithreaded experience. I've played around with it in the past for fun but I think gaining some experience with a throw-away application will suit your future efforts.
I wish you luck in this endeavor and I must admit I wish I had the opportunity to work on something like this...