Eu encontrei um site pelo Google que explicava como trabalhar com tipos unsigned em Java, ou melhor, como não trabalhar, pois Java não tem isso. Basicamente o texto dizia para usar um tipo maior do que se é esperado ler e fazer operações de bit shifting para setá-lo. Por exemplo, usar um int se o valor esperado é 16 bit, ou um short se o valor esperado é um byte.
A minha pergunta, não importa o site, é que li que internamente a JVM usa um inteiro de 32 bits, mesmo se o valor que você quer usar é um short ou um byte. Ou seja, não há economia alguma em se usar esses tipos menores. Isso é correto?
E também que operações com long não são atômicas, ou seja, a VM pode interromper a operação no meio para outra thread trabalhar. Isso também é correto?
Eu encontrei um site pelo Google que explicava como trabalhar com tipos unsigned em Java, ou melhor, como não trabalhar, pois Java não tem isso. Basicamente o texto dizia para usar um tipo maior do que se é esperado ler e fazer operações de bit shifting para setá-lo. Por exemplo, usar um int se o valor esperado é 16 bit, ou um short se o valor esperado é um byte.
A minha pergunta, não importa o site, é que li que internamente a JVM usa um inteiro de 32 bits, mesmo se o valor que você quer usar é um short ou um byte. Ou seja, não há economia alguma em se usar esses tipos menores. Isso é correto?
[/quote]
Importa-se em colocar as referências?
Isso é parcialmente correto. A spec da JVM não diz quantos bytes devem ser usados para representar cada tipo. O que existe é que a pilha de valores temporários (a JVM é uma máquina de pilha) é toda especificada usando tipos de 4bytes (ints…), e quando um byte/short é lido ele é expandido p/ 4bytes. Isso é até normal de ser feito, dado que que a execução é mais rápida se a pilha conter apenas valores de 4 bytes. Porém as JVMs usam os tamanhos certos na hora de representar um objeto e arrays.
[quote=Thiagosc]
E também que operações com long não são atômicas, ou seja, a VM pode interromper a operação no meio para outra thread trabalhar. Isso também é correto?[/quote]
Parcialmente correto. A spec não garante a atomicidade de operações em longs. Isso não tem relação direta com parar uma thread no meio, mesmo por que em uma máquina multi-processada isso não é necessario para perceber o efeito.
Oque existe é que ela não garante a visibilidade total de uma atualização em um long/double de uma thread p/ outra. Isso quer dizer, uma thread pode ler apenas 4 bytes do novo valor de um long que outra thread está atribuindo. Em uma máquina de 64bits isso não ocorre por que a maioria suporta operações com 8 bytes. Esse problema de visibilidade é muito mais provavel de acontecer quando o número de cpus é alto.
a) De qualquer maneira, se você precisa de um long "atômico", você pode usar java.util.concurrent.AtomicLong.
b) Os operadores >>> e >>>= preenchem parcialmente o "buraco" que existe por o Java não ter tipos "unsigned". (Até em Modula-3 existe o tal tipo - CARDINAL, e se não me engano em Ada também. É uma omissão do James Gosling que ele deve lamentar até hoje.).
Em C++:
unsigned int x = 0xCAFEBABE; // supondo um compilador onde 1 int = 32 bits
int y = 0xCAFEBABE;
x >>= 2; // resultado = 0x32BFAEAF
y >>= 2; // resultado = 0xF2BFAEAF
Em Java:
int x = 0xCAFEBABE;
int y = 0xCAFEBABE;
x >>>= 2; // resultado = 0x32BFAEAF
y >>= 2; // resultado = 0xF2BFAEAF