我正在学习Java中的多线程。以下是演示代码,我对函数内Thread.yield()
的使用感到好奇。
它不是同步函数,在运行任务完成其工作之前无法调用它吗?然后将Thread.yield()
插入此块之间有什么区别?
演示代码:
public class SynchronizeEvenGenerator {
private int currentEvenValue = 0;
/**
* Generate even and return it
* @return
*/
public synchronized int next() {
++currentEvenValue;
Thread.yield();
++currentEvenValue;
return currentEvenValue;
}
}
答案 0 :(得分:3)
如果在同步函数中调用
Thread.yield()
会发生什么?
Thread.yield()
状态为javadoc:
" [这是]调度程序提示当前线程愿意产生其当前使用的处理器。调度程序可以忽略此提示。"
所以有两种可能性:
yield()
电话会立即返回。yield()
调用返回。不会发生一件事。线程不放弃互斥锁。碰巧被阻止等待获取互斥锁的任何其他线程将保持被阻止。
它不是一个同步方法,在运行任务完成其工作之前无法调用吗?
Thread.yield
不是同步方法。 (即使它是,它将锁定Thread
对象,而不是synchronized
块当前持有的锁。)
因此,在您的示例中,对next()
的调用保证将计数器正好递增2.如果某个其他线程调用next()
方法,则第二个调用将保持阻塞状态(至少)在第一次通话后返回。
javadoc也说了这个:
"使用此方法很少合适。"
另一个问题:它是否会成为线程调度的死锁
没有。调用yield()
的线程最终将被重新安排。
(死锁是一种非常具体的现象(参见Wikipedia article),只有在获得锁定时才会发生。当一个线程产生时,它既不会获取或释放锁定,也不会导致死锁。)
现在,当一个线程产生时,它可能需要很长时间再次被调度,特别是如果有许多其他可运行的线程处于相同的或更高的优先级。最终结果是等待获取锁的其他线程可能会持续很长时间。这可能会过度增加争用和拥塞。但最终,yield()
调用将返回,next()
调用将返回,另一个线程将能够获取锁。
简而言之:在持有锁时调用yield()
对性能不利,但它不会直接导致死锁。
正如javadoc所说,调用yield()
很少适合。
答案 1 :(得分:1)
这是不是一个同步函数,在运行任务完成它之前无法调用它?
它不能在同一个对象的另一个线程中运行。
然后将Thread.yield()插入此块之间的差异是什么?
正在运行线程的CPU可以上下文切换到系统上任何进程的另一个可用线程。
如果没有等待线程运行,它将使其慢约15-30微秒。
c.f。 wait(0),这可以允许另一个线程获得锁。