gpt4 book ai didi

c++ - 池化线程的 SetThreadAffinityMask

转载 作者:可可西里 更新时间:2023-11-01 12:07:13 30 4
gpt4 key购买 nike

我想知道是否可以设置从线程池中获取的线程的处理器关联性。更具体地说,线程是通过使用我用来实现周期性任务的 TimerQueue API 获得的。

作为旁注:我发现 TimerQueues 是实现周期性任务的最简单方法,但由于这些通常是长期任务,为此目的使用专用线程是否更合适?此外,预计需要使用信号量和互斥量等同步原语来同步各种周期性任务。池线程适合这些吗?

谢谢!

EDIT1:正如 Leo 指出的那样,上述问题实际上是两个松散相关的问题。第一个与池线程的处理器亲和性有关。第二个问题与从 TimerQueue API 获得的池化线程在涉及同步对象时的行为是否与手动创建的线程一样。我将把第二个问题移到一个单独的主题中。

最佳答案

如果您这样做,请确保每次将线程释放回池中时都恢复到原来的状态。由于您不拥有这些线程和使用它们的其他代码可能有其他要求/假设。

不过,您确定确实需要这样做吗?需要设置处理器亲和性的情况非常非常罕见。 (我不认为我曾经需要在我写的任何东西中这样做。)

线程亲和性可能意味着两个完全不同的事情。(感谢 bk1e 对我的原始答案的评论指出了这一点。我自己没有意识到。)

  1. 我称之为处理器亲和性:线程需要在同一处理器上始终如一地运行。这就是 SetThreadAffinityMask 处理的内容,代码很少关心它。 (通常这是由于非常低级的问题,例如高性能代码中的 CPU 缓存。通常操作系统会尽最大努力将线程保持在同一个 CPU 上,而强制它不这样做通常会适得其反。)

    <
  2. 我称之为线程亲和性:对象使用线程本地存储(或与访问它们的线程相关的其他一些状态)并且如果一系列 Action 不在同一个线程上完成。

从您的问题看来,您可能混淆了#1 和#2。线程本身不会更改当您的回调运行时。当一个线程正在运行时,它可能会在 CPU 之间跳转,但这是正常的,您不必担心(除非在非常特殊的情况下)。

互斥量、信号量等不关心线程是否在 CPU 之间跳转。

如果您的回调被线程池多次执行,(取决于池的使用方式)通常不能保证每次都使用同一个线程。也就是说,您的回调可能会在线程之间跳转,但不会在运行过程中跳转;它可能只会在每次再次运行时更改线程。

一些同步对象关心您的回调代码是否在一个线程上运行,然后仍然认为它持有这些对象的锁,在另一个线程上再次运行。 (第一个线程仍将持有锁,而不是第二个线程,尽管这取决于您使用的是哪种同步对象。有些人不关心。)不过,这不是 #1;那是 #2,而不是你会使用 SetThreadAffinityMask 来处理的东西。

例如,互斥量 (CreateMutex) 由线程拥有。如果您在线程 A 上获取互斥锁,那么任何其他试图获取该互斥锁的线程都将阻塞,直到您释放线程 A 上的互斥锁。(线程释放它不拥有的互斥锁也是一个错误。)因此,如果你的回调获得了一个互斥量,然后退出,然后在另一个线程上再次运行并从那里释放了互斥量,这是错误的。

另一方面,事件 (CreateEvent) 不关心哪个线程创建、发信号或销毁它。您可以在一个线程上发出事件信号,然后在另一个线程上重置它,这很好(实际上是正常的)。

在回调的两次独立运行之间保存同步对象的情况也很少见(这会引起死锁,尽管在某些情况下您可以合法地想要/做这样的事情)。但是,如果您创建(例如)一个单元线程 COM 对象,那么您可能只想从一个特定线程访问它。

关于c++ - 池化线程的 SetThreadAffinityMask,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4268019/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com