【问题标题】:What does Thread Affinity mean?线程亲和力是什么意思?
【发布时间】:2013-11-04 10:09:15
【问题描述】:

我在某处听说过 Thread Affinity 和 Thread Affinity Executor。但至少在java中我找不到合适的参考。谁能给我解释一下这是怎么回事?

【问题讨论】:

    标签: java multithreading concurrency terminology


    【解决方案1】:

    有两个问题。首先,线程最好与某个 CPU(核心)具有亲和力,以充分利用其 CPU 本地缓存。这必须由操作系统处理。这个用于线程的CPU affinity 通常也称为“线程亲和性”。在 Java 的情况下,没有标准的 API 来控制它。但是正如其他答案所提到的,有 3rd 方库。

    其次,在 Java 中观察到,在典型的程序中对象是线程仿射的,即通常大多数时间只由一个线程使用。因此,JVM 优化器的任务是确保与一个线程相关的对象在内存中彼此靠近放置以适应一个 CPU 的高速缓存,但将与不同线程相关的对象放置在彼此之间不要太近以避免它们共享一个缓存行,否则两个 CPU/核心必须过于频繁地同步它们。

    理想的情况是,一个 CPU 可以独立地处理某些对象,而另一个 CPU 可以处理放置在不相关内存区域中的其他对象。

    考虑Java对象的线程亲和性的优化的实际例子是

    • Thread-Local Allocation Buffers (TLABs)

      使用 TLAB,每个对象的生命周期都在专用于创建它的线程的内存区域中开始。根据分代垃圾收集器背后的主要假设(“所有对象中的大多数将在年轻时死去”),大多数对象将在这样的线程本地缓冲区中度过其整个生命周期。

    • Biased Locking

      使用偏向锁定,JVM 将执行锁定操作,乐观假设对象将仅由同一线程锁定,仅当此假设不成立时才切换到更昂贵的锁定实现。

    • @Contended

      为了解决另一端,即已知可被多个线程访问的字段,HotSpot/OpenJDK 有一个注释(目前不属于公共 API)来标记它们,以指示 JVM 将这些数据从其他可能未共享的数据。

    【讨论】:

    • @Holger 你能否提供一些链接,根据 jvm world 进行更详细的解释?
    • @DmitryZagorulkin 我扩展了答案
    【解决方案2】:

    让我试着解释一下。随着多核处理器的兴起,线程和线程池之间的消息传递,调度变得更加昂贵。为什么这比以前重得多,因为我们需要了解“机械同情”的概念。有关详细信息,您可以通过blog 了解它。但简而言之,当线程分布在处理器的不同内核上时,当它们尝试交换消息时;缓存未命中概率很高。现在谈到您的具体问题,线程亲和性能够将特定线程分配给特定的处理器/内核。这是可以用于java的library之一。

    【讨论】:

    • 不知道为什么有人反对这个答案。被否决的人应该提到这个答案有什么问题。我挑战它没有任何问题。这很好。
    【解决方案3】:

    Java Thread Affinity version 1.4 library 试图实现两全其美,允许您为关键线程保留逻辑线程,并为性能最敏感的线程保留整个内核。不太关键的线程仍将利用超线程的优势运行。例如以下代码sn-p

    AffinityLock al = AffinityLock.acquireLock();
        try {
            // find a cpu on a different socket, otherwise a different core.
            AffinityLock readerLock = al.acquireLock(DIFFERENT_SOCKET, DIFFERENT_CORE);
            new Thread(new SleepRunnable(readerLock, false), "reader").start();
    
            // find a cpu on the same core, or the same socket, or any free cpu.
            AffinityLock writerLock = readerLock.acquireLock(SAME_CORE, SAME_SOCKET, ANY);
            new Thread(new SleepRunnable(writerLock, false), "writer").start();
    
            Thread.sleep(200);
        } finally {
            al.release();
        }
    
        // allocate a whole core to the engine so it doesn't have to compete for resources.
        al = AffinityLock.acquireCore(false);
        new Thread(new SleepRunnable(al, true), "engine").start();
    
        Thread.sleep(200);
        System.out.println("\nThe assignment of CPUs is\n" + AffinityLock.dumpLocks());
    

    【讨论】:

      【解决方案4】:

      线程亲和性(或进程亲和性)描述了允许线程/进程在哪些处理器内核上运行。通常,此设置等于系统中的(逻辑)CPU,并且几乎没有理由更改此设置,因为操作系统具有在可用处理器之间安排任务的最佳可能性。

      请参阅 http://msdn.microsoft.com/en-us/library/windows/desktop/ms683213(v=vs.85).aspx 了解它在 Windows 中的工作原理。我不知道 java 是否提供 API 来设置这些。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-04-06
        • 2019-03-03
        • 2018-10-22
        • 2015-06-02
        • 1970-01-01
        • 2018-07-05
        • 2015-10-05
        • 2012-08-11
        相关资源
        最近更新 更多