系列前面验证过 setPriority() 在真实调度里几乎没有效果,这篇换成 Thread.yield()——结果完全相反,效果大到夸张,同一台10核机器上,差距真实是500倍级别。
上一篇:Arrays.binarySearch() 真实验证
两个线程做同样的空转计数,一个每次循环调用Thread.yield(),一个完全不调用,300毫秒后对比完成次数。
ThreadYieldDemo.java Thread yielding = new Thread(() -> { while (!stop.get()) { c++; Thread.yield(); } }); Thread normal = new Thread(() -> { while (!stop.get()) { c++; } });
第1轮: 调用yield()的线程真实完成次数=1520664, 不调用yield()的线程真实完成次数=897428085, 比例=0.002 第2轮: 调用yield()的线程真实完成次数=1676430, 不调用yield()的线程真实完成次数=926965966, 比例=0.002 第3轮: 调用yield()的线程真实完成次数=1655559, 不调用yield()的线程真实完成次数=916975998, 比例=0.002
yield()调用期间,main线程手里持有的synchronized锁,是否会被真实释放出去?
ThreadYieldDemo.java synchronized (lock) { other.start(); // other线程试图抢同一把lock Thread.yield(); // main线程真实调用yield(),但依然在synchronized块内部 System.out.println(secondEntered.get()); }
main线程持锁期间调用yield(),其他线程真实能否进入: false(应为false,yield()不释放锁) main线程真实释放锁后,其他线程真实能否进入: true
真实结果证明了一个容易被误解的边界:yield() 影响的只是"当前线程是否继续占用CPU执行权",和"当前线程持有的锁"是两个完全独立的概念。main 线程在 synchronized 块内部调用 yield(),即使 CPU 执行权真的被让出去了,lock 这把锁依然真实被 main 线程持有,其他线程真实无法进入同步块——这和 wait()(会真实释放锁)是本质不同的两种机制,不能把 yield() 当作一种"临时让路"的同步手段来用。
每一行都是真实运行这段代码得到的结果。