【问题标题】:What Use are Threads Outside of Parallel Problems on MultiCore Systems?多核系统上并行问题之外的线程有什么用处?
【发布时间】:2010-12-29 11:23:31
【问题描述】:

线程使程序的设计、实现和调试变得更加困难。

然而,许多人似乎认为程序中可以线程化的每个任务都应该是线程化的,即使在单核系统上也是如此。

我可以理解像 MPEG2 解码器这样将在多核 cpu 上运行的线程(我已经这样做了),但是当您谈论单核系统甚至如果您的任务没有从并行实现中获得显着的性能,那么是多核系统吗?

或者更简洁地说,什么样的与性能无关的问题可以证明线程是合理的?

编辑

我刚刚遇到了一个不受 CPU 限制但线程有很大不同的实例:

TCP, HTTP and the Multi-Threading Sweet Spot

在尝试通过高延迟网络连接将带宽最大化到另一个对等方时,多线程非常有用。非阻塞 I/O 将使用更少的本地 CPU 资源,但设计和实现会更加困难。

【问题讨论】:

    标签: multithreading language-agnostic concurrency


    【解决方案1】:

    例如,在不阻塞用户界面的情况下执行 CPU 密集型任务。

    【讨论】:

    • 好的,但是核心功能和接口位于通过某种 IPC(例如套接字)进行通信的独立进程中的模型呢?我知道很多开源项目都使用这个模型。我从事过的项目中,核心功能和 GUI 不必要地相互耦合,而实际上它们应该是单独的进程。我认为在单独的进程中拥有 CPU 密集型功能将使单元测试和 Q/A 等事情变得更加简单。将它们与线程保持在同一进程中而不是拆分的论据是什么?
    • 嘿,我只是指出了一种使用线程的可能场景,这就是问题所在。我从未声称它是不阻塞 UI 的唯一选择。
    【解决方案2】:

    您可能正在等待资源(例如,阻止来自网络套接字或磁盘设备的 I/O)的任何应用程序都可以从线程中受益。

    在这种情况下,慢速操作上的线程阻塞可以在其他线程继续运行时进入睡眠状态(包括,在某些操作系统下,GUI 线程,如果操作系统暂时无法联系它,将提供趁机摧毁它,以为它不知何故陷入僵局。

    所以它根本不只是多核机器。

    【讨论】:

    • 也许吧,但是对于 I/O,我可以通过信号和信号处理程序获得异步通知,在我看来这比处理线程要简单得多。 en.wikipedia.org/wiki/Asynchronous_I/O#Signals_.28interrupts.29
    • 在信号处理程序中可以做的事情有限(我倾向于为真实代码设置标志)。使用线程没有这样的限制。
    【解决方案3】:

    一个有趣的例子是网络服务器 - 您需要能够处理多个相互无关的传入连接。

    【讨论】:

    • 这是我想到的场景之一。但传统上你只是用这种问题分叉。据我了解,Apache 2 从分叉切换到线程,但实际上,由于进程和线程在 Linux 上几乎相同且成本相等,因此他们的投资回报率有多大?
    【解决方案4】:

    什么样的非性能相关 问题证明线程合理?

    Web 应用程序是典型的例子。每个用户请求在概念上都是一个新线程。与性能无关,它只是设计的自然契合。

    【讨论】:

    • 也许吧,但这个问题的传统解决方案是分叉。至少在 Linux 上,进程和线程的成本几乎相同,你真正从线程超过分叉中获得多少?
    • 线程和分叉在概念上是一回事。线程只是一个轻量级进程,多线程网络服务器将分叉一个线程而不是一个进程。
    • 一个线程和它的父线程在同一个内存空间中运行,而一个分叉的进程在它自己的内存空间中运行,你必须使用管道或其他进程间通信的方法。
    • 如果您使用 cookie 将 HTTP 请求映射到有状态会话,例如,分叉进程必须使用 IPC 来获取和更新该状态。
    【解决方案5】:

    阻塞代码通常比非阻塞代码更容易编写和阅读(因此也更容易维护)。然而,使用阻塞代码会将您限制在单一的执行路径上,并且还会锁定用户界面(提到的)和其他 IO 端口之类的东西。在这些情况下,线程是一种优雅的解决方案。

    要考虑多线程的另一种情况是当您有几个应该管理的接近同步的 IO 通道时:使用多个线程(通常是本地消息队列)可以使代码更清晰。

    【讨论】:

      【解决方案6】:

      以下是我启动线程的几个具体而简单的场景...

      1. 用户长时间运行的报告请求。当报告被提交时,它被放置在一个队列中,由一个单独的线程处理。然后,用户可以在应用程序中继续,稍后再回来查看报告的状态,他们不会留下“处理中...”页面或图标。

      2. 循环缓存存储的线程,删除已过期或不再需要的数据。应用程序中线程的工作独立于特定用户的任何处理,而是整个应用程序运行时维护的一部分。

      3. 虽然不是专门的线程场景,但我们网站内的日志记录被移交给并行进程,因此网站的吞吐量不会受到记录日志数据所需时间的阻碍。

      我同意仅仅为了线程而线程不是一个好主意,如果处理不当,它可能会在您的应用程序中引入问题,但它是解决某些问题的非常有用的工具。

      【讨论】:

        【解决方案7】:

        当您需要调用一些仅提供同步/阻塞接口或使用异步接口的外部组件(无论是数据库查询、3.party 库、操作系统原语等)时,不值得额外的麻烦和痛苦——你还需要某种形式的并发——例如在服务器中为多个客户端提供服务或保持 GUI 仍然响应。

        【讨论】:

          【解决方案8】:

          那么,您如何知道您的应用程序是否将在多核系统上运行?

          除此之外,还有很多进程会占用时间,但不需要 CPU。例如写入磁盘或网络。谁想在 GUI 中按下按钮,然后不得不坐在那里等待网络连接。即使在单核机器上,拥有单独的 IO 线程也能极大地提升用户体验。您总是至少需要一个单独的 UI 线程。

          【讨论】:

            【解决方案9】:

            然而很多人似乎认为 程序中的每一项任务都可以 线程应该是线程的,即使在 单核系统。

            “很多人”...谁?

            根据我的经验,许多应该是多线程的程序也不是(尤其是游戏。我有一个 i7,但大多数游戏仍然只使用我的一个内核),所以我不确定你在说什么关于。像calc.exe 这样的程序绝对不是多线程的(或者,如果是,1 个线程可以完成 99% 的工作)。

            执行 CPU 密集型任务 在不阻塞用户界面的情况下, 例如。

            是的,这是真的,但这很容易实现,这不是 OP 所指的(因为在这种情况下,1 个线程几乎可以完成所有工作,而您只需要很少的互斥锁)

            【讨论】:

              猜你喜欢
              • 2023-04-02
              • 2012-04-19
              • 1970-01-01
              • 2019-05-19
              • 2013-07-01
              • 2011-06-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多