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

池化线程的SetThreadAffinityMask
EN

Stack Overflow用户
提问于 2010-11-24 22:44:17
回答 2查看 800关注 0票数 1

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

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

谢谢!

EDIT1:正如Leo所指出的,上述问题实际上只是两个松散相关的问题。第一个问题与池化线程的处理器亲和性有关。第二个问题是,当涉及到同步对象时,从TimerQueue应用编程接口获得的池化线程的行为是否与手动创建的线程相同。我将把第二个问题移到另一个主题。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-11-24 22:56:56

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

你确定你真的需要这样做吗?很少需要设置处理器亲和性。(我不认为在我写的任何东西中都需要这样做。)

BK1E线程亲和性可能意味着两个完全不同的东西。(感谢BK1E对我最初回答的评论指出了这一点。我还没有意识到我自己。)

  1. ,我称之为processor affinity:线程需要在同一处理器上一致运行。这就是SetThreadAffinityMask要处理的事情,很少有代码会关心它。(通常是由于高性能代码中的CPU缓存等非常低级的问题造成的。通常,操作系统会尽最大努力将线程放在同一个CPU上,强制它这样做通常会适得其反。我称之为线程亲和性:其中对象使用线程本地存储(或绑定到从其访问它们的线程的其他状态),如果没有在同一线程上完成一系列操作,则会出错。

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

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

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

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

例如,Mutexes (CreateMutex)归一个线程所有。如果你在线程A上获取了一个互斥锁,那么任何其他试图获取该互斥锁的线程都会被阻塞,直到你释放线程A上的互斥锁为止。(线程释放一个不属于它的互斥锁也是一个错误。)因此,如果您的回调获取了一个互斥锁,然后退出,然后在另一个线程上再次运行并从那里释放互斥锁,那就错了。

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

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

票数 2
EN

Stack Overflow用户

发布于 2010-11-24 22:58:02

你不应该这样做,你只应该把这个线程用在手头的任务上,在它运行的处理器上。除了明显的效率低下之外,线程池可能会在您完成后立即销毁每个线程,并为您的下一项工作创建一个新线程。在实践中,亲和性掩码不会很快消失,但如果它们随机消失,调试起来就更难了。

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

https://stackoverflow.com/questions/4268019

复制
相关文章

相似问题

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