简体   繁体   English

为什么多线程环境被认为是有害的?

[英]Why is a multithreaded environment considered harmful?

我知道如果使用了很多范围广泛的状态,这是一个坏主意,但是不可变的计算和高度局部化的副作用又如何呢?

Debugging multi-threaded code is hard. 调试多线程代码很困难。 Really hard. 真的很难。

While mitigating state, and proper design can reduce this difficulty it still remains much more difficult than debugging single threaded code. 在减轻状态的同时,适当的设计可以减少这种困难,但与调试单线程代码相比,它仍然要困难得多。

Thus multi-threading for multi-threading's sake is a design pathology. 因此,出于多线程的考虑,多线程是一种设计病理。

That being said, there are plenty of cases where using >1 thread is the right decision. 话虽这么说,在很多情况下,使用> 1线程是正确的决定。

To over-simplify things, functional languages such as Erlang and Haskell are built around the notion that multithreaded apps are very safe when you eliminate side effects. 为简化起见,Erlang和Haskell等功能语言是围绕这样的概念构建的:多线程应用程序在消除副作用时非常安全。 You should read about those. 您应该阅读这些内容。 Also, in general a multithreaded application with no shared state is quite safe. 而且,通常,没有共享状态的多线程应用程序是相当安全的。

http://en.wikipedia.org/wiki/Haskell_%28programming_language%29 http://en.wikipedia.org/wiki/Haskell_%28programming_language%29

http://en.wikipedia.org/wiki/Erlang_%28programming_language%29 http://en.wikipedia.org/wiki/Erlang_%28programming_language%29

Multithreaded programming isn't considered harmful, but rather notoriously difficult to be done right. 多线程编程不被认为是有害的,但是众所周知,很难正确完成。 There are many things that aren't evident from the first sight and may lead to things like deadlocks and race conditions. 乍一看,有很多事情是看不到的,并可能导致死锁和比赛条件。

Immutable computations and functional programming is one way to deal with the complexity of multithreaded programming. 不变的计算和函数式编程是处理多线程编程复杂性的一种方法。 With multi-core systems becoming ubiquitous today, there is a general consensus that the programmer shouldn't be left on his own to program in mulithread environment, but rather she should rely on a framework or a library. 在当今多核系统无处不在的情况下,人们普遍达成共识,即程序员不应该独自在多线程环境中编程,而应该依赖于框架或库。 In .NET environment parallel extensions will be part of the 4.0 version of the framework for example. 例如,在.NET环境中,并行扩展将是框架4.0版本的一部分。

A lot of people approach multi-threading as if it were the silver bullet to peformance problems. 许多人都将多线程当作解决性能问题的灵丹妙药。 Take for example the relatively common case of doing a "computationally intense operation", the operation is irrelevant. 以进行“计算密集的操作”的相对常见的情况为例,该操作是不相关的。

A common misconception is that by making the operation multi-threaded we can speed it up. 一个常见的误解是,通过使操作成为多线程,我们可以加快操作速度。 The specifics of this are much more complicated. 具体细节要复杂得多。 It depends on what the process is and how much "waiting" there is in the process. 这取决于过程是什么以及过程中有多少“等待”。 If the process is very tight, putting it into a multi-threaded environment will at best speed it up marginally, and in most cases it will make it considerably slower. 如果该过程非常紧张,则最好将其放入多线程环境中,以最快的速度提高速度,并且在大多数情况下,它将使其速度大大降低。

There are also the consideration of managing state, managing thread interaction and the problems with determinism introduced by threads. 还需要考虑管理状态,管理线程交互以及线程引入的确定性问题。

The list of course goes on from there. 当然清单从那里继续。

Multithreading in C++ is hard because (among other things): C ++中的多线程很难,因为(除其他外):

  • Every modification of a variable must be done within a critical section. 变量的每次修改都必须在关键部分内完成。 It is hard to see from a statical analysis of the source code which variable needs such locking. 从源代码的静态分析中很难看出哪个变量需要这种锁定。
  • The scope of critical sections must be small enough to avoid performance issues, but using a separate critical section for each variable is often impossible, because multiple variables must be updated simultaneously. 关键部分的范围必须足够小以避免出现性能问题,但是对于每个变量使用单独的关键部分通常是不可能的,因为必须同时更新多个变量。
  • Nested critical sections must be used hierarchically. 嵌套的关键部分必须按层次使用。 However, tools that can enfore this at compile time don't exist. 但是,尚不存在可以在编译时实现此目的的工具。
  • When bugs occur, they are often hard to reproduce because of timing issues. 发生错误时,由于时序问题,它们通常很难重现。 Because of this, the code is both hard to test and difficult to debug. 因此,代码既难以测试又难以调试。
  • Stepping through an asynchronous function call is impossible without setting breakpoints manually, because C++ has no built-in threading support. 如果不手动设置断点,就不可能单步执行异步函数调用,因为C ++没有内置的线程支持。

The algorithm that you are using in your single-threaded program may or may not be easy to scale to multiple threads. 您在单线程程序中使用的算法可能难以扩展到多个线程。

For example, if you want to do multi-threaded image compression, some formats are inherently tiled, so you can assign a thread to each tile, but for example Lossless JPEG is based on nearest neighbour prediction, so the value of the last pixel is potentially dependent on all the values in between, and therefore this algorithm is unsuitable for division among multiple threads. 例如,如果要执行多线程图像压缩,则某些格式会固有地进行平铺,因此可以为每个平铺分配一个线程,但是例如,“无损JPEG”基于最近的邻居预测,因此最后一个像素的值为可能取决于它们之间的所有值,因此该算法不适合在多个线程之间进行划分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM