【问题标题】:What will happen when insert the `Thread.yield()` into an synchronized function将 `Thread.yield()` 插入同步函数时会发生什么
【发布时间】:2018-06-04 09:59:24
【问题描述】:

我正在学习 Java 中的多线程。下面是demo代码,很好奇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;
    }
}

【问题讨论】:

    标签: java multithreading task synchronized


    【解决方案1】:

    如果在同步函数中调用Thread.yield() 会发生什么?

    正如javadocThread.yield() 所述:

    “[This is a] 提示调度程序,当前线程愿意让出其当前使用的处理器。调度程序可以随意忽略此提示。”

    所以有两种可能:

    1. 什么都没有发生;即yield() 调用立即返回。
    2. 另一个线程被调度并开始执行。最终,此线程被重新安排,yield() 调用返回。

    一件事没有发生。线程不会放弃互斥锁。任何其他碰巧被阻塞等待获取互斥锁的线程将保持阻塞。


    它不是一个同步方法,直到运行的任务完成它的工作才能调用它?

    Thread.yield 不是同步方法。 (即使是这样,它也会锁定 Thread 对象,而不是 synchronized 块当前持有的锁。)


    因此,在您的示例中,对next() 的调用保证将计数器递增2。如果其他线程调用next() 方法,则第二次调用将保持阻塞状态,直到(至少)在第一次调用之后调用返回。

    javadoc 也这样说:

    “使用这种方法很少合适。”


    另一个问题:会不会成为线程调度的死锁

    没有。调用yield() 的线程最终将被重新调度。

    (死锁是一种非常特殊的现象(见Wikipedia article),只有在获得锁时才会发生。当线程屈服时,它既不获取也不释放锁,因此不会导致死锁。)

    现在,当一个线程屈服时,它可能需要很长时间才能再次被调度,特别是如果有许多其他具有相同或更高优先级的可运行线程。最终结果是等待获取锁的其他线程可能会等待很长时间。这会过度增加争用和拥塞。但最终,yield() 调用将返回,next() 调用将返回,另一个线程将能够获取锁。

    简而言之:在持有锁的同时调用yield() 对性能不利,但不会直接导致死锁。

    正如 javadoc 所说,调用 yield() 很少合适。

    【讨论】:

    • 另一个问题:会不会成为线程调度的死锁?
    【解决方案2】:

    它不是一个同步函数,直到正在运行的任务完成它的工作才能调用?

    它不能在同一对象的另一个线程中运行。

    那么将 Thread.yield() 插入这个块和不插入有什么区别?

    正在运行线程的 CPU 可以上下文切换到系统上任何进程的另一个可用线程。

    如果没有等待线程运行,它会使其慢约 15 - 30 微秒。

    参考wait(0) 可以让另一个线程获得锁。

    【讨论】:

    • 只是延迟方法执行,不会产生任何其他影响?
    • @BinXiao 正确,此时线程可能会以任何方式屈服,但它更有可能。
    • 那么可用的线程是什么? (那些线程不需要运行这个函数?)
    • @BinXiao 同一进程中的任何线程,或任何其他进程或内核中的一个。将有数千个可能的线程可以在您的机器上运行。
    猜你喜欢
    • 1970-01-01
    • 2023-01-03
    • 2015-09-01
    • 2013-07-04
    • 2017-03-20
    • 2014-11-11
    • 2013-09-17
    • 1970-01-01
    • 2020-03-04
    相关资源
    最近更新 更多