繁体   English   中英

Java线程与CPU内核的关系

[英]Java threads relation to CPU cores

假设我有2个核心的CPU。 如果我将使用Executors.newFixedThreadPool(4)线程运行后台处理服务,我是否正确:

  1. 在执行程序服务的生命周期内,单线程可能在不同的内核上运行
  2. 即使没有同步,如果线程A在内核1上运行其代码并留在CPU缓存中,也可以说是共享单例的某个值,然后,如果线程B将在同一内核上运行其代码,并尝试从具有线程A在高速缓存中留下的表示形式-它将从CPU核心L1或L2高速缓存中获取它。 如果线程B将使用同步,它将从主内存(最新版本)中读取新值。 通常,如果在CPU内核中保留的某个线程缓存了共享对象的私有字段的某个值-可以在同一内核上运行的另一个线程可能会从其他线程留下的缓存中看到私有成员的值。
  3. 如果最上面的两个选项都为真-如果L2高速缓存将用于存储线程之间的共享(这将添加新值映射)HashMap实例和L2将为所有核心高速缓存之间的共享-这是否意味着在跳过时不是原子的操作(如果我们只想查看map中的正确/最新值),则可以跳过同步。 例如,拥有HashMap并从Map读取现有值时跳过同步是否正确:

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class Launcher {


public static void main(String[] args) throws Exception {
    final Stats stats = new Stats();
    final Random key = new Random();

    ExecutorService service = Executors.newFixedThreadPool(2);

    service.submit(new Runnable() {
        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                String keyValue = String.valueOf(key.nextInt(10));
                int value = stats.inc(keyValue);
                System.out.println("[A] Key " +  keyValue + " was incremented to " + value);
                try {
                    TimeUnit.MILLISECONDS.sleep(1500);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    });

    service.submit(new Runnable() {
        @Override
        public void run() {
            while (!Thread.currentThread().isInterrupted()) {
                int[] values = new int[10];
                for (int i = 0; i< 10; i++) {
                    values[i] = stats.get(String.valueOf(i));
                }

                System.out.println("[B] " + Arrays.toString(values));
                try {
                    TimeUnit.MILLISECONDS.sleep(1500);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }
    });
}
static class Stats {

    private final Map<String, Number> statistics = new HashMap<String, Number>();

    public int inc(String key) {
        if (!statistics.containsKey(key)) {
            synchronized (statistics) {
                statistics.put(key, new AtomicInteger(0));
            }
        }

        return ((AtomicInteger) statistics.get(key)).getAndIncrement();
    }

    public int get(String key) {
        if (!statistics.containsKey(key)) {
            return 0;
        }
        return statistics.get(key).intValue();
    }
}
}

您能否指出一些有价值的Java低级多线程代码管理文档?

伙计们,我真的很明白我们不应该依赖于特定的体系结构/ CPU /等等。我很好奇所描述的点的概率是否大于0 :)

提前Thx

除非在访问上同步或使变量可变,否则您不应对线程看到其他线程修改的值做任何假设。

任何其他行为都是不可靠的,并且可能会发生变化。

请记住,Java是在JVM上运行的,而不是直接在您的处理器上运行的,并且具有对运行代码进行大量优化的许可。 因此,尽管许多行为都可以延续,但您不能依靠它。 特别是因为一旦您在不同的体系结构上运行或在不同的条件下运行,则可能完全不同地优化了完全相同的字节码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM