java - 什么是快速、等待通知或忙等待?

标签 java multithreading

我知道使用 busy-wait 不是一个好的编程习惯,最好尽可能使用同步对象 (wait-notify)。但我想知道是否准备好牺牲 cpu 周期,那么忙等待会更快还是等待通知?

我假设 wait-notify 将涉及对同步对象的内部锁定,并且信号可能来自内核以唤醒线程,这使得这种方法比忙等待慢得多,后者可以连续检查条件直到满意为止。一旦满足此条件(例如 boolean 值 == true),线程就可以从忙等待中解脱出来。根据我的理解,我觉得忙等待应该更快。

如果我的论点有误,如果其他人能分享他们的想法并纠正我,我将不胜感激。

最佳答案

实验表明,如果您忙于等待,您会比等待并通知(无论如何在我的硬件上)更快地看到标志。 (详情如下。)区别是非常非常非常非常小,因此这只适用于非常罕见的应用程序。例如,股票交易应用程序,如果公司追求他们可以获得的任何优势(争先恐后地将他们的服务器定位在尽可能靠近交易所的位置,以便从交易所获得微秒级的网络反馈等),可能会认为这种差异是值得的。我也可以想象一些科学应用。

在绝大多数应用中,差异实际上没有任何差异。

但是发生在 CPU 上的当然是核心硬 Hook 之一:

hardpeg

就影响盒子上的其他进程和数据中心的功耗而言,这很糟糕。

因此:极不情愿地使用,仅在真正重要的情况下使用。


数据(非常小的样本,但代码如下):

Busy Wait:       10631  12350  15278
Wait and Notify: 87299 120964 107204
Delta:           76668 108614  91926

Times are in nanoseconds. Billionths of a second. The average delta above is 92403ns (0.092402667 milliseconds, 0.000092403 seconds).

BusyWait.java:

public class BusyWait {

    private static class Shared {
        public long setAt;
        public long seenAt;
        public volatile boolean flag = false;
    }

    public static void main(String[] args) {
        final Shared shared = new Shared();
        Thread notifier = new Thread(new Runnable() {
            public void run() {
                System.out.println("Running");
                try {
                    Thread.sleep(500);
                    System.out.println("Setting flag");
                    shared.setAt = System.nanoTime();
                    shared.flag = true;
                }
                catch (Exception e) {
                }
            }
        });
        notifier.start();
        while (!shared.flag) {
        }
        shared.seenAt = System.nanoTime();
        System.out.println("Delay between set and seen: " + (shared.seenAt - shared.setAt));
    }
}

WaitAndNotify.java:

public class WaitAndNotify {

    private static class Shared {
        public long setAt;
        public long seenAt;
        public boolean flag = false;
    }

    public static void main(String[] args) {
        (new WaitAndNotify()).test();
    }
    private void test() {
        final Shared shared = new Shared();
        final WaitAndNotify instance = this;
        Thread notifier = new Thread(new Runnable() {
            public void run() {
                System.out.println("Running");
                try {
                    Thread.sleep(500);
                    System.out.println("Setting flag");
                    shared.setAt = System.nanoTime();
                    shared.flag = true;
                    synchronized (instance) {
                        instance.notify();
                    }
                }
                catch (Exception e) {
                }
            }
        });
        notifier.start();
        while (!shared.flag) {
            try {
                synchronized (this) {
                    wait();
                }
            }
            catch (InterruptedException ie) {
            }
        }
        shared.seenAt = System.nanoTime();
        System.out.println("Delay between set and seen: " + (shared.seenAt - shared.setAt));
    }
}

关于java - 什么是快速、等待通知或忙等待?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24948791/

相关文章:

java - 如何链接到 Java 8 供应商

java - 找不到 Tomcat 7 setenv.sh

java - System.in默认指的是什么?

c# - 启动多个线程并从我的 .NET 应用程序中跟踪它们

java - Hibernate 模式验证失败,MySQL CHAR 映射到 String

java - 继承和多态分配

c# - 在后台使用非托管库时无法更新 WPF GUI

java - 当我重新打开应用程序时,如何检查上一个 session 中的线程是否仍在运行?

java - 如何让两个线程从一个输入流读取数据?

java - 如何使 JLabel 上的 ImageIcon 更新速度更快、延迟更短