java wait() 和 yield() 的区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26798073/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 10:37:26  来源:igfitidea点击:

difference between wait() and yield()

javamultithreading

提问by Awani

So far what I have understood about wait() and yield () methods is that yield() is called when the thread is not carrying out any task and lets the CPU execute some other thread. wait() is used when some thread is put on hold and usually used in the concept of synchronization. However, I fail to understand the difference in their functionality and i'm not sure if what I have understood is right or wrong. Can someone please explain the difference between them(apart from the package they are present in).

到目前为止,我对wait() 和yield() 方法的理解是当线程不执行任何任务时调用yield() 并让CPU 执行某个其他线程。wait() 在某个线程被搁置时使用,通常用于同步的概念。但是,我无法理解它们的功能差异,我不确定我所理解的是对还是错。有人可以解释一下它们之间的区别吗(除了它们所在的包装)。

回答by Solomon Slow

aren't they both doing the same task - waiting so that other threads can execute?

他们不是都在做同样的任务——等待以便其他线程可以执行吗?

Not even close, because yield()does not waitfor anything.

甚至不关闭,因为yield()等待任何事情。

Every thread can be in one of a number of different states: Runningmeans that the thread is actually running on a CPU, Runnablemeans that nothing is preventing the thread from running except, maybe the availability of a CPU for it to run on. All of the other states can be lumped into a category called blocked. A blocked thread is a thread that is waiting for something to happen before it can become runnable.

每个线程可以在多个不同状态之一: 运行表示线程实际上是一个CPU上运行,可运行的手段,没有什么会阻止线程除外,一个CPU为它运行的可能可用性运行。所有其他国家都可以集中到一个名为类别封锁。阻塞的线程是在它变得可运行之前等待某些事情发生的线程。

The operating system preemptsrunning threads on a regular basis: Every so often (between 10 times per second and 100 times per second on most operating systems) the OS tags each running thread and says, "your turn is up, go to the back of the run queue' (i.e., change state from running to runnable). Then it lets whatever thread is at the head of the run queue use that CPU (i.e., become running again).

操作系统定期抢占正在运行的线程:操作系统每隔一段时间(在大多数操作系统上为每秒 10 次到每秒 100 次)标记每个正在运行的线程并说:“轮到你了,转到后面运行队列'(即,将状态从运行更改为可运行)。然后它让运行队列头部的任何线程使用该 CPU(即再次运行)。

When your program calls Thread.yield(), it's saying to the operating system, "I still have work to do, but it might not be as important as the work that some other thread is doing. Please send me to the back of the run queue right now." If there is an available CPU for the thread to run on though, then it effectively will just keep running (i.e., the yield() call will immediately return).

当您的程序调用 时Thread.yield(),它对操作系统说:“我还有工作要做,但它可能不如其他线程正在做的工作重要。请立即将我送到运行队列的后面。 ” 如果有一个可用的 CPU 供线程运行,那么它实际上将继续运行(即,yield() 调用将立即返回)。

When your program calls foobar.wait()on the other hand, it's saying to the operating system, "Block me until some other thread calls foobar.notify().

foobar.wait()另一方面,当您的程序调用时,它对操作系统说:“阻止我,直到其他线程调用foobar.notify().

Yielding was first implemented on non-preemptive operating systems and, in non-preemptive threading libraries. On a computer with only one CPU, the onlyway that more than one thread ever got to run was when the threads explicitly yielded to one another.

Yielding 最初是在非抢占式操作系统和非抢占式线程库中实现的。在只有一个 CPU 的计算机上,运行多个线程的唯一方法是线程明确地相互让步。

Yielding also was useful for busy waiting. That's where a thread waits for something to happen by sitting in a tight loop, testing the same condition over and over again. If the condition depended on some other thread to do some work, the waiting thread would yield() each time around the loop in order to let the other thread do its work.

Yielding 对忙碌的等待也很有用。这就是线程通过坐在一个紧密的循环中,一遍又一遍地测试相同条件来等待某事发生的地方。如果条件依赖于其他线程来做一些工作,等待的线程会在每次循环中 yield() 以便让其他线程完成它的工作。

Now that we have preemption and multiprocessor systems and libraries that provide us with higher-level synchronization objects, there is basically no reason why an application programs would need to call yield()anymore.

既然我们拥有为我们提供更高级别同步对象的抢占和多处理器系统和库,那么应用程序基本上就没有理由再需要调用yield()了。

回答by Holger

waitis for waitingon a condition. This might not jump into the eye when looking at the method as it is entirely up to you to define what kind of condition it is. But the API tries to force you to use it correctly by requiring that you own the monitor of the object on which you are waiting, which is necessary for a correct condition check in a multi-threaded environment.

wait等待一个条件。在查看方法时,这可能不会引起人们的注意,因为完全由您来定义它是什么类型的条件。但是 API 试图通过要求您拥有正在等待的对象的监视器来强制您正确使用它,这是在多线程环境中进行正确条件检查所必需的。

So a correct use of waitlooks like:

所以正确使用wait看起来像:

synchronized(object) {
  while( ! /* your defined condition */)
    object.wait();
  /* execute other critical actions if needed */
}

And it must be paired with another thread executing code like:

它必须与另一个执行代码的线程配对,例如:

synchronized(object) {
  /* make your defined condition true */)
  object.notify();
}


In contrast Thread.yield()is just a hintthat your thread might release the CPU at this point of time. It's not specified whether it actually does anything and, regardless of whether the CPU has been released or not, it has no impact on the semantics in respect to the memory model. In other words, it does not create any relationship to other threads which would be required for accessing shared variables correctly.

相反,Thread.yield()这只是暗示您的线程此时可能会释放 CPU。没有具体说明它是否真的做任何事情,无论 CPU 是否被释放,它对内存模型的语义没有影响。换句话说,它不会与正确访问共享变量所需的其他线程建立任何关系。

For example the following loop accessing sharedVariable(which is not declared volatile) might run forever without ever noticing updates made by other threads:

例如,以下循环访问sharedVariable(未声明volatile)可能会永远运行而不会注意到其他线程所做的更新:

while(sharedVariable != expectedValue) Thread.yield();

While Thread.yieldmight help other threads to run (they will run anyway on most systems), it does notenforce re-reading the value of sharedVariablefrom the shared memory. Thus, without other constructs enforcing memory visibility, e.g. decaring sharedVariableas volatile, this loop is broken.

虽然Thread.yield可能有助于其他线程运行(它们无论如何都会在大多数系统上运行),但它不会强制sharedVariable从共享内存中重新读取 的值。因此,如果没有其他结构强制执行内存可见性,例如 decaring sharedVariableas volatile,这个循环就被打破了。

回答by indian

The first difference is that yield()is a Threadmethod , wait()is at the origins Objectmethod inheritid in threadas for all classes , that in the shape, in the background (using java doc)

第一个区别是它yield()是一个Thread方法,wait()在所有类的起源Object方法inheritid中thread,在形状中,在后台(使用java doc)

wait()

Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).

使当前线程等待,直到另一个线程为此对象调用 notify() 方法或 notifyAll() 方法。换句话说,这个方法的行为就像它只是执行调用 wait(0) 一样。

yield()

A hint to the scheduler that the current thread is willing to yield its current use of a processor. The scheduler is free to ignore this hint.

向调度程序提示当前线程愿意放弃其当前对处理器的使用。调度程序可以随意忽略此提示。

and here you can see the differencebetween yield()and wait()

在这里你可以看到yield()wait()之间的区别