在大多数语言/框架中,存在一种线程将控制权交给其他线程的方法。但是,我真的想不出从线程中产生是给定问题的正确解决方案的时候。一般来说,什么时候应该使用Thread.yield()
,sleep(0)
等?
3 回答
一个用例可能是测试并发程序,尝试找到揭示同步模式中缺陷的交错。例如在 Java 中:
增加交错次数并因此更有效地探索程序的状态空间的一个有用技巧是在访问共享状态的操作
Thread.yield
期间鼓励更多的上下文切换。(这种技术的有效性是特定于平台的,因为 JVM 可以自由地将 THRead.yield 视为无操作 [JLS 17.9];使用短暂但非零的睡眠会更慢但更可靠。) — JCIP
从 Java 的角度来看,还有趣的是它们的语义没有定义:
Thread.yield
(and )的语义Thread.sleep(0)
未定义 [JLS 17.9];JVM 可以自由地将它们实现为无操作或将它们视为调度提示。特别是,它们不需要在 Unix 系统上具有 sleep(0) 的语义,将当前线程放在该优先级的运行队列的末尾,让给具有相同优先级的其他线程,尽管一些 JVM 以这种方式实现 yield。— JCIP
当然,这使得它们相当不可靠。这是非常特定于 Java 的,但是,总的来说,我相信以下是正确的:
两者都是可用于影响调度顺序的低级机制。如果这是用来实现某个功能,那么这个功能是基于 OS 调度程序的概率,这似乎是一个相当糟糕的主意。这应该由更高级别的同步结构来管理。
出于测试目的或强制程序进入某种状态,它似乎是一个方便的工具。
让您的操作系统调度程序为您决定?
所以永远不要屈服,永远不要 sleep(0),直到你匹配到 sleep(0) 绝对必要的情况并在此处记录。
上下文切换也很昂贵,所以我认为很多人不想要更多的上下文切换。
一般来说,什么时候应该使用 Thread.yield()、sleep(0) 等?
这取决于我们正在谈论的VM是线程模型。对我来说,答案很少(如果有的话) 。
传统上,一些线程模型是非抢占式的,而另一些则(或曾经)不成熟,因此需要Thread.yield()
.
我觉得这Thread.yield()
就像register
在 C 中使用一样。我们过去常常依靠它来提高程序的性能,因为在许多情况下,程序员在这方面比编译器要好。但是现代编译器要聪明得多,而且现在程序员可以通过使用register
and来提高程序性能的情况越来越少Thread.yield()
。