gpt4 book ai didi

Java 线程与 CPU 内核的关系

转载 作者:行者123 更新时间:2023-11-30 07:11:27 25 4
gpt4 key购买 nike

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

  1. 在执行程序服务的生命周期内,单个线程可以在不同的内核上运行
  2. 即使没有同步,如果线程 A 在核心 1 上运行它的代码并在 CPU 缓存中留下一些共享单例的值,那么如果线程 B 将在同一个核心上运行它的代码并尝试从同一个内存中获取单例值线程 A 在缓存中留下表示的位置 - 它将从 CPU 核心 L1 或 L2 缓存中获取它。如果线程 B 将使用同步,它将从主内存(最新版本)读取新值。一般来说,如果某个线程留在 CPU 核心缓存共享对象的私有(private)字段的某些值 - 可以在同一核心上运行的另一个线程可以从其他线程留下的缓存中看到私有(private)成员的值。
  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 多线程代码低级管理的有值(value)的文档吗?

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

提前致谢

最佳答案

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

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

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

关于Java 线程与 CPU 内核的关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21197409/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com