线程亲和性是什么意思?

57

我曾经听说过线程亲和性和线程亲和性执行器。但至少在Java中,我找不到合适的参考资料。有人能否解释一下这是什么意思?

4个回答

60

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

其次,在Java中观察到,在典型程序中对象是线程相关的,即大多数情况下仅由一个线程使用。因此,JVM的优化器的任务是确保将亲和于一个线程的对象放置在内存中彼此靠近,以适应一个CPU的缓存,但不要将亲和于不同线程的对象放置得太靠近,以避免它们共享缓存行,否则两个CPU / Core必须过于频繁地进行同步。

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

考虑Java对象的线程亲和性的实际优化示例包括:

  • 线程本地分配缓冲区(TLAB)

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

  • 偏向锁定

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

  • @Contended

    为了解决另一端,即已知由多个线程访问的字段,HotSpot / OpenJDK具有一个注释(当前不是公共API的一部分),用于标记它们,以指示JVM将这些数据移开,远离其他潜在未共享的数据。


@Holger,您能否提供一些更详细的链接,以便了解JVM世界的相关内容? - Dmitry Zagorulkin
1
@DmitryZagorulkin 我扩展了答案。 - Holger

13
让我试着解释一下。随着多核处理器、线程之间的消息传递和线程池的兴起,调度变得更加耗费资源。为什么这比以前更加沉重,我们需要理解“机械同理心”这个概念。有关详细信息,您可以查看此博客。但是简单来说,当线程分布在处理器的不同核心上时,尝试交换消息时会产生高缓存未命中率。现在针对您的具体问题,线程亲和力能够将特定的线程分配到特定的处理器/核心。这里是其中一个java的可供使用。

8
不知道为什么有人对这个答案点了踩。踩的人应该说出这个答案的问题所在。我质疑这个答案没有任何问题。这完全没问题。 - Prateek

5

Java Thread Affinity version 1.4库旨在兼顾两者优点,让您为关键线程保留逻辑线程,并为性能最敏感的线程保留整个核心。不太关键的线程仍将享受超线程的好处。例如以下代码片段:

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());

3
线程亲和性(或进程亲和性)描述了线程/进程可以运行在哪些处理器核心上。通常,这个设置等于你系统中的(逻辑)CPU数量,而且几乎没有理由改变这个设置,因为操作系统会最好地安排你的任务在可用的处理器之间进行调度。
请参见例如http://msdn.microsoft.com/en-us/library/windows/desktop/ms683213(v=vs.85).aspx,了解Windows中如何运作。我不知道Java是否提供API来设置这些内容。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接