首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >线程中的线程?

线程中的线程?
EN

Stack Overflow用户
提问于 2012-05-15 17:58:00
回答 3查看 17.7K关注 0票数 5

我想用pthread实现分而治之,但是我不知道如果我在一个线程中创建更多的线程会发生什么。

据我所知,如果机器有2核处理器,它只能同时处理2个线程。如果有2个以上的线程,其他线程必须等待资源,所以如果我在更深的地方创建越来越多的线程,实际上可能不会提高算法的速度,因为同时只能处理2个线程。

我在网上做了一些研究,似乎上层的线程可能是不活跃的,只有最深层的线程才保持活跃。如何做到这一点?另外,如果上层线程保持非活动状态,是否会影响底层线程?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-05-15 18:06:47

有两种基本类型:分离的和可接合的。

可接合线程是您可以使用pthread_join等待(或访问)终止的线程。

使用比核心更多的线程可能会有帮助,也可能会有坏处--这取决于您的程序!使用多线程来最小化或消除对资源的竞争通常是有好处的。在一个程序中抛出太多的线程实际上会减慢进程。但是,如果内核数量与线程计数相匹配,并且其中一个线程正在等待磁盘IO (假设其他进程中没有发生重大事件),则可能会有空闲的CPU时间。

较高级别的

线程可以处于非活动状态,只有最深级别的线程才保持活动状态。如何做到这一点?

使用可接合线程,您可以完成您概述的嵌套线程方法,这在几个教程中进行了演示。基本流程是,线程将创建一个或多个工作进程,并使用pthread_join等待它们退出。但是,在大多数情况下,任务和线程池等替代方案更可取。

然而,这种方法不太可能是最好的执行方法,因为它不能(很好地)与硬件和调度操作相关联,特别是随着程序的深度和宽度的增长。

如果上层线程保持不活动,是否不会影响下层线程?

是。然而,典型的问题是工作/线程不受约束。使用您概述的方法,很容易产生许多线程,并且对于必须在有限数量的内核上执行的工作来说,具有不合理的高线程数量。因此,您的程序将浪费大量时间进行上下文切换和等待线程完成。创建多个线程也会浪费/保留大量资源,特别是如果它们是短暂的和/或空闲/等待的。

,所以如果我创建越来越多的线程,同时深入到更深的地方,实际上它可能不会增加算法的速度,因为同时只能处理2个线程。

这表明使用这种方法创建线程是有缺陷的。您可能希望创建几个线程,并使用基于任务的方法--其中每个线程请求并执行集合中的任务。创建线程需要花费大量的时间和资源。

票数 6
EN

Stack Overflow用户

发布于 2012-05-15 18:45:02

如果你正在尝试做一个双向的分而治之,产生两个孩子并等待他们完成,你可能需要这样的东西:

代码语言:javascript
复制
void *
routine (void * argument)
{
  /* divide */
  left_arg = f (argument);
  right_arg = f (argument);

  /* conquor */
  pthread_create (left_child, NULL, routine, left_arg);
  pthread_create (right_child, NULL, routine, right_arg);

  /* wait for 'children' */
  pthread_join (left_child, &left_return_val);
  pthread_join (right_child, &right_return_val);

  /* merge results & return */
}

一个轻微的改进是,“父线程”不是休眠,而是同步地完成正确的子线程的工作,并少产生一个线程:

代码语言:javascript
复制
void *
routine (void * argument)
{
  /* divide */
  left_arg = f (argument);
  right_arg = f (argument);

  /* conquor */
  pthread_create (left_child, NULL, routine, left_arg);
  /* do the right_child's work yourself */
  right_return_val = routine (right_arg);

  /* wait for 'left child' */
  pthread_join (left_child, &left_return_val);

  /* merge results & return */
}

然而,当你深入到N层时,你会有相当多的孩子。获得的加速比实际上取决于CPU在实际处理上花费了多少时间,以及它等待I/O的时间等。如果你知道在有P内核的机器上,你只能通过kP线程获得良好的加速比,那么你可以设置一个kP线程的“worker pool”,并不断地重用它们,而不是像上面那样产生线程。这样,一旦产生了kP线程,就不会产生更多的线程:

代码语言:javascript
复制
THREAD_POOL pool = new_thread_pool (k * P); /* I made this function up */

void *
routine (void * argument)
{
  /* divide */
  left_arg = f (argument);
  right_arg = f (argument);

  /* conquor */
  left_thread = get_worker (pool); /* Blocks until a thread is free  */
  /* get left_thread to do processing for you */

  right_thread = get_worker (pool); /* Blocks until a thread is free  */
  /* get right_thread to do processing for you */

  /* wait for 'children' */
  pthread_join (left_child, &left_return_val);
  pthread_join (right_child, &right_return_val);

  /* return the workers */
  put_worker (pool, left_thread);
  put_worker (pool, right_thread);

  /* merge results & return */
}
票数 2
EN

Stack Overflow用户

发布于 2012-05-15 18:10:37

您应该能够创建比系统中的内核多得多的线程。操作系统将确保每个线程都让CPU的一部分来完成它的工作。

但是,您可以创建的线程数可能有一个上限(请查看您的操作系统文档)。

因此,如果您在一个具有2个核心的系统中创建5个线程,那么每个线程将获得大约40%的cpu (平均)。这并不是说一个线程必须等到另一个线程完全完成。当然,除非你使用锁。

当您使用锁来保护数据不被多线程更改或访问时,可能会出现许多问题。典型问题包括:

  • 死锁:线程1等待由线程2锁定的东西;线程2等待由线程1锁定的东西
  • 锁车队:多个线程都在等待同一个锁
  • 优先级反转:线程1在线程2上具有优先级,但由于线程2在大部分时间都有一个锁,线程1仍然必须等待线程2

我找到了这个页面(http://ashishkhandelwal.arkutil.com/index.php/csharp-c/issues-with-multithreaded-programming-part-1/),它可能是多线程编程的一个很好的开端。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10598303

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档