根据java文档全面解析Thread.yield()方法

    /**(1)
     * 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.
     *(2)
     * <p> Yield is a heuristic attempt to improve relative progression
     * between threads that would otherwise over-utilise a CPU. Its use
     * should be combined with detailed profiling and benchmarking to
     * ensure that it actually has the desired effect.
     *(3)
     * <p> It is rarely appropriate to use this method. It may be useful
     * for debugging or testing purposes, where it may help to reproduce
     * bugs due to race conditions. It may also be useful when designing
     * concurrency control constructs such as the ones in the
     * {@link java.util.concurrent.locks} package.
     */
     public static native void yield();

(1)当前线程暗示调度器,它愿意让出对CPU的使用。调度器可以忽略这个暗示,也可以做出相应处理。

    说明:如果调度器忽略了这个暗示,那么当前线程将会继续执行,不会停止。如果调度器没有忽略,则当前线程会从执行状态转化为就绪状态,然后调度器会从就绪状态的线程中,选择一个出来,让它使用CPU。

(2)yield方法的初衷是为了提高线程之间的相对进度,防止过度使用CPU的。所以yield方法的使用,一定要经过详细的分析和测试,确保yield能达到预期的效果。

    说明:也就是说要知道yield方法可能会被忽略。我们要在这个前提下,去正确使用yield。

(3)适合yield方式使用的场景不多。有需要使用到的地方,一个是竞态条件下为了复现bug,使用yield用于调试。另一个是同步控制的设计需要。

下面举个例子,说明一个yield的使用场景(一定是和while()循环搭配使用的):

  public static void main(String[] args) throws InterruptedException {
        final AtomicInteger ai = new AtomicInteger(1);
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!ai.compareAndSet(2, 3))
                    Thread.yield();//当ai的值还没有被赋值为2的时候,线程让出CPU使用权
            }
        });

        t.start();
        if (ai.compareAndSet(1, 2)) {//将2赋值给ai
            t.join();//等待t线程运行完再往下执行,相当于把线程t的代码加进来了
            if (!t.isAlive()) {
                int a = ai.get();
                System.out.println("a = " + a);//a = 3
            } else {
                System.out.println("t线程还在运行中");//如果t.join()注释掉的话,会打印这句,否则永远不会打印
            }
        }
    }

可以看出来,t 线程想要把ai的值从2更新为3,需要等待主线的把ai的值从1更新为2以后。所以线程 t 在更新ai值失败以后,调用yield方法,让出了cpu的使用权。如果这时候被调度器忽略的,会继续去更新ai的值。这是ai的值可能是2了,也可能不是。如果不是,t线程会继续重复上述步骤,直到成功赋值为3。(和我们预期的是一样的)

觉得有用的老铁们赞一下呗,谢谢!

发布了78 篇原创文章 · 获赞 131 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/river66/article/details/91492758