Suplemento de conhecimento de CPU
Execução fora de ordem da CPU
package com.mashibing.jvm.c3_jmm;
public class T04_Disorder {
private static int x = 0, y = 0;
private static int a = 0, b =0;
public static void main(String[] args) throws InterruptedException {
int i = 0;
for(;;) {
i++;
x = 0; y = 0;
a = 0; b = 0;
Thread one = new Thread(new Runnable() {
public void run() {
//由于线程one先启动,下面这句话让它等一等线程two. 读着可根据自己电脑的实际性能适当调整等待时间.
//shortWait(100000);
a = 1;
x = b;
}
});
Thread other = new Thread(new Runnable() {
public void run() {
b = 1;
y = a;
}
});
one.start();other.start();
one.join();other.join();
String result = "第" + i + "次 (" + x + "," + y + ")";
if(x == 0 && y == 0) {
System.err.println(result);
break;
} else {
//System.out.println(result);
}
}
}
public static void shortWait(long interval){
long start = System.nanoTime();
long end;
do{
end = System.nanoTime();
}while(start + interval >= end);
}
}
Pode haver problemas com execução fora de ordem (existente em multi-threading) -> por que o DCL é volátil? -> desabilitar a reordenação de instruções
Quando um objeto é criado, haverá um estado intermediário. Neste momento, as variáveis de membro são todos os valores padrão.
Se o volátil não for adicionado, pode ocorrer o rearranjo da instrução. O ponteiro do objeto aponta para a variável com o valor padrão antecipadamente. Neste momento, outros threads vêm para pegar o objeto, então
Como desabilitar a reordenação de instruções no nível da CPU ?
Garantia ordenada
Nível da CPU
-
Barreira de memória X86CPU
- sfence: A operação de gravação antes da instrução sfence deve ser concluída antes da operação de gravação após a instrução sfence
- Infence: A operação de leitura antes da instrução sfence deve ser concluída antes da operação de leitura após a instrução sfence
- mfence: As operações de leitura e gravação antes da instrução mfence devem ser concluídas antes das operações de leitura e gravação após a instrução mfence
-
instrução de montagem intel lock Instruções
atômicas, como a instrução "lock..." no X86, são uma barreira completa que bloqueia o subsistema de memória quando executada para garantir a ordem de execução, mesmo em várias CPUs.
Os bloqueios de software normalmente usam barreiras de memória ou instruções atômicas para obter visibilidade variável e manter a ordem do programa.
Nível JVM
Barreira de memória JSR
-
Barreira LoadLoad:
Para tais declarações Load1, LoadLoad, Load2
Antes que os dados a serem lidos por Load2 e as operações de leitura subsequentes sejam acessados, é garantido que os dados a serem lidos por Load1 foram lidos. -
Barreira StoreStore:
Para tais instruções Store1, StoreStore, Store2,
antes que Store2 e as operações de gravação subsequentes sejam executadas, as operações de gravação de Store1 são garantidamente visíveis para outros processadores. -
Barreira LoadStore:
Para tais instruções Load1, LoadStore e Store2
, os dados a serem lidos por Load1 têm a garantia de serem lidos antes que Store2 e as operações de gravação subsequentes sejam liberadas. -
Barreira StoreLoad:
Para tais instruções Store1, StoreLoad, Load2,
antes de load2 e todas as operações de leitura subsequentes serem executadas, as gravações de Store1 são garantidamente visíveis para todos os processadores.
Extensão: detalhes de implementação do volátil
No nível da JVM
, a barreira subjacente é implementada pela instrução de bloqueio
Extensão: princípio acontece antes
as if serial: Não importa o quão reordenado, o resultado da execução single-thread não mudará, parece serial.
Nível JVM: 8 princípios hanppens-before 4 barreiras de memória (LL LS SL SS)
mesclar gravação
Geralmente são 4 bytes,
como a ALU é muito rápida, um WC Buffer é escrito ao mesmo tempo em que L1 é escrito, e depois de cheio é atualizado diretamente para L2.
package com.mashibing.juc.c_029_WriteCombining;
public final class WriteCombining {
private static final int ITERATIONS = Integer.MAX_VALUE;
private static final int ITEMS = 1 << 24;
private static final int MASK = ITEMS - 1;
private static final byte[] arrayA = new byte[ITEMS];
private static final byte[] arrayB = new byte[ITEMS];
private static final byte[] arrayC = new byte[ITEMS];
private static final byte[] arrayD = new byte[ITEMS];
private static final byte[] arrayE = new byte[ITEMS];
private static final byte[] arrayF = new byte[ITEMS];
public static void main(final String[] args) {
for (int i = 1; i <= 3; i++) {
System.out.println(i + " SingleLoop duration (ns) = " + runCaseOne());
System.out.println(i + " SplitLoop duration (ns) = " + runCaseTwo());
}
}
public static long runCaseOne() {
long start = System.nanoTime();
int i = ITERATIONS;
//这个循环一共写6次
while (--i != 0) {
int slot = i & MASK;
byte b = (byte) i;
arrayA[slot] = b;
arrayB[slot] = b;
arrayC[slot] = b;
arrayD[slot] = b;
arrayE[slot] = b;
arrayF[slot] = b;
}
return System.nanoTime() - start;
}
public static long runCaseTwo() {
long start = System.nanoTime();
int i = ITERATIONS;
//每个循环4次写操作
while (--i != 0) {
int slot = i & MASK;
byte b = (byte) i;
arrayA[slot] = b;
arrayB[slot] = b;
arrayC[slot] = b;
}
i = ITERATIONS;
while (--i != 0) {
int slot = i & MASK;
byte b = (byte) i;
arrayD[slot] = b;
arrayE[slot] = b;
arrayF[slot] = b;
}
return System.nanoTime() - start;
}
}
NUMA
UMA: Várias CPUs compartilham a mesma memória
Desvantagem: Não é fácil expandir, e o aumento do número de CPUs fará com que os conflitos de acesso à memória se intensifiquem. Muitos recursos da CPU são desperdiçados lutando por endereços de memória. 4 NUMA adequados
(acesso à memória não uniforme): memória de acesso não uniforme. A partir da placa-mãe, a CPU e a memória serão divididas em slots diferentes.ZGC
usa NUMA-Aware: alocar memória dará prioridade à memória recente da CPU onde a thread está localizada.
Noções básicas do sistema operacional
comece
Ligar -> bios uefi work -> autoteste -> carregar bootloader para a posição fixa do disco rígido -> ler informações configuráveis -> CMOS
O que é um sistema operacional
O que o sistema operacional faz principalmente
Breve estrutura
núcleo núcleo
kernel de macro
Uso: telefone PC
microkernel
Objetivo: O
núcleo da implantação elástica de 5G IoT é o agendamento de processos
Núcleo externo (apenas entenda)
Objetivo: Personalizar o sistema operacional para aplicativos em experimentos de pesquisa científica (JVM de GC baseada em solicitação de vários locatários)
VMM
monitor de máquina virtual
Modo de usuário e modo de kernel
CPU é dividida em diferentes níveis de instrução
O kernel Linux é executado no nível do anel 0 e o programa do usuário é executado no nível do anel 3. Quanto ao anel 1 e anel 2, nem o anel 1 nem o anel 2 são usados; para acesso de chave ao sistema, é necessário o consentimento do kernel para garantir a robustez do sistema.
o que o kernel faz -> apenas 200+ syscalls sendfile read write pthread fork
JVM -> Do ponto de vista do chefe do sistema operacional, é um programa comum, portanto, no modo de usuário