繁体   English   中英

Thread.Yield是否会让CPU进行上下文切换到同一进程或同一处理器中的其他线程?

[英]Does Thread.Yield will let the CPU do context switch to other thread in the same process or same processor?

我在Joseph Albahari的Threading本书( http://www.albahari.com/threading/ )中看到以下内容

Thread.Sleep(0)立即放弃线程的当前时间片,自动将CPU移交给其他线程。 Framework 4.0的新Thread.Yield()方法做同样的事情-只是它只放弃运行在同一处理器上的线程。

上下文切换是否发生在同一进程内或正在等待获取CPU的线程中?

如果答案是后者,那么有什么方法可以将上下文切换到同一进程中处于等待状态的其他线程吗?

我了解到,线程调度已由操作系统处理。 但是,由于Thread.Sleep(0)并试图找到解决方案而感到震惊。

编辑以使问题更清晰:

该软件有两个线程(例如A和B),A将等待来自B的信号20毫秒,然后不管该信号如何继续进行。 A设置信号并让处理器继续使用B,因为该软件是时间紧迫的应用程序,因此每秒钟都会发生一次,因此应用Thread.Sleep(0)。 一秒钟,A和B都没有继续并恢复(在日志的帮助下知道)。 我们以为同一处理器中的其他进程获得了CPU时间片,现在正在寻找替代方案。

Thread.Yield方法将切换到准备在当前处理器上运行的任何线程。 Thread在哪个进程中没有任何区别

即使通过P / Invoke,也无法在同一进程中屈服于另一个线程。 Windows根本不支持它。

一种替代方法是使用某种协作式多任务处理,例如TPL和async / await。 当您await诸如Task.Yield()返回的awaitable对象之类的东西时,它将使另一个与调度程序排队的任务启动。 它也比使用Thread.Yield()效率更高,但是如果您不使用它,则可能需要对应用程序进行大修。

Thread.Yield()将仅允许调度程序在准备运行的同一进程中选择另一个线程,并在已停止的任何点恢复它。 它与进程之间的时间分片无关,这是完全不同的事情。 (而且很少关注,除非您也正在对其他进程进行编程。)

请注意,如果当前线程是唯一可以运行的线程,则Yield()可能根本不起作用。 它只会从Yield()调用中返回(相对立即)。

您对“上下文在同一进程中切换到另一个线程”的问题有点误解。 您不应该用这些话来思考。 如果您需要等待另一个线程完成 ,请使用Join。 如果您需要发信号通知另一个线程它应该停止等待并执行某些操作,则可以使用多种机制。

简而言之,如果您试图“猜测”线程调度程序,那么问题将会变得更加严重。

也许您应该更清楚地了解实际遇到的问题。

线程是OS线程的包装。 由于线程的调度是由OS内核执行的,因此Yield只是一种告诉内核的方式,您希望放弃CPU但仍保持可运行状态(未阻塞)。 内核会将您的请求视为执行重新调度并将CPU分配给其他等待线程的好地方。 OS可以自由地将CPU分配给运行队列中的任何等待线程,而无需考虑它所属的进程。 除非它是您自己的调度程序,并且您使用所谓的绿色线程和协作式多任务处理,否则无法影响调度程序的决策。

关于您的问题:如果要获得有保证的结果,则需要使用显式同步。 屈服是错误的方法,因为它无法为您提供任何保证。 使用它可能会出现很多问题。 例如,线程B可能没有足够的时间来完成其工作并将信号发送给A,然后再对A进行调度; A可以在Yield到另一个CPU内核之后立即进行调度; A甚至可以在B之前重新进行调度将有机会被处决。 最后,其他应用程序可以占用CPU。 如果您真的很在意时间,请提高两个线程的优先级,但要显式同步它们。

暂无
暂无

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

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