Pergunta

Eu quero incrementar um inteiro sem sinal de vários segmentos.

Eu sei sobre Interlocked.Increment, mas não lidar com números inteiros sem sinal. Eu poderia usar lock (), mas eu prefiro não, se possível, por razões de desempenho.

É enfiar apenas seguro para incrementá-lo de uma forma normal? Isso não importa se o incremento ocasional se perdeu, como ele é usado apenas para as estatísticas. O que eu não quero é o valor a ser corrompidos.

Foi útil?

Solução

Você diz que não quer usar lock por motivos de desempenho - mas você já testou? Um bloqueio incontestável (o que é provável que isto seja, pelos sons dele) é muito barato.

Eu geralmente vão para "obviamente correta" ao invés de "inteligente e possivelmente melhor desempenho" quando se trata de enfiar (e, em geral, mas especialmente para rosqueamento).

Referência seu aplicativo com e sem bloqueio, e veja se você ainda pode notar a diferença. Se o bloqueio faz um significativa diferença, então a certeza, coisas uso astuto. Caso contrário, eu tinha acabado de ficar com um bloqueio.

Uma coisa que você pode quer fazer é usar Interlocked.Increment com um int e apenas lançá-lo quando necessário para obter uma uint, como este:

using System;
using System.Reflection;
using System.Threading;

public class Test
{
    private static int count = int.MaxValue-1;

    public static uint IncrementCount()
    {
        int newValue = Interlocked.Increment(ref count);
        return unchecked((uint) newValue);
    }

    public static void Main()
    {
        Console.WriteLine(IncrementCount());
        Console.WriteLine(IncrementCount());
        Console.WriteLine(IncrementCount());
    }

}

Output:

2147483647
2147483648
2147483649

(Em outras palavras, envolve sem problemas.)

Outras dicas

Se você realmente precisa de toda a gama de um int sem sinal (2 ^ 32 - 1) em vez de um int assinado (2 ^ 31 -1), você poderia lançar a um int64 (há uma sobrecarga Interlocked.Increment que leva int64) e então lançou de volta para um int não assinado.

Em sistemas usando um pares representação complemento de inteiros assinados ( "praticamente todos" , de acordo com a Wikipedia) incrementando um número inteiro sem sinal tem o mesmo efeito como incrementando um número inteiro assinado representada utilizando o mesmo conjunto de bits. Assim, pode-se usar InterlockedIncrement em números inteiros sem sinal sem sacrificar nada.

Por exemplo, com 3 bits temos a tabela a seguir:

raw bits | unsigned integer | twos complement signed integer
------------------------------------------------------------
000      |                0 |                             0 
001      |                1 |                             1 
010      |                2 |                             2 
011      |                3 |                             3 
100      |                4 |                            -4 
101      |                5 |                            -3
110      |                6 |                            -2
111      |                7 |                            -1

Incrementando por um (e tendo estouro em conta) é equivalente a mover uma entrada para baixo na tabela, em ambos os casos. Note-se que esta não funciona para aqueles complementar aritmética, já que os negativos são organizados em ordem inversa.

você pode declarar a uint tão volátil.

http://msdn.microsoft.com /en-us/library/x13ttww7(VS.71).aspx

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top