Domanda

Voglio incrementare un intero senza segno da più thread.

So di Interlocked.Increment, ma non gestisce interi senza segno. Potrei utilizzare il blocco (), ma preferirei non, se possibile, per motivi di prestazioni.

E 'thread-safe solo per incrementarlo in modo normale? Non importa se l'incremento occasionale ha perso, come è utilizzato solo per le statistiche. Quello che non voglio è il valore da ottenere danneggiato.

È stato utile?

Soluzione

Tu dici che non si desidera utilizzare lock per ragioni di prestazioni - ma avete provato? Un blocco incontrastato (che questo è probabile che sia, dai suoni di esso) è piuttosto a buon mercato.

Io in genere vado per "ovviamente corretto" piuttosto che "intelligente e forse meglio performante" quando si tratta di threading (e, in generale, ma soprattutto per la filettatura).

Benchmark la tua app con e senza blocco, e vedere se si può anche notare la differenza. Se il blocco fa un significativo differenza poi certo, utilizzare roba astuzia. In caso contrario, avevo appena bastone con una serratura.

Una cosa che potrebbe vuole fare è utilizzare Interlocked.Increment con una int e proprio cast, se necessario, per ottenere un uint, in questo modo:

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

(In altre parole si avvolge senza problemi.)

Altri suggerimenti

Se davvero bisogno di tutta la gamma di un unsigned int (2 ^ 32 - 1) piuttosto che un int firmato (2 ^ 31 -1), in cui potresti giocare un Int64 (c'è un sovraccarico Interlocked.Increment che prende Int64) e poi gettato di nuovo ad un unsigned int.

Su sistemi che utilizzano una rappresentazione di complemento a due interi con segno ( "praticamente tutti" , secondo wikipedia) incrementare un numero intero senza segno ha lo stesso effetto di incrementare un intero con segno rappresentata utilizzando lo stesso insieme di bit. Così, si può usare InterlockedIncrement su numeri interi senza segno, senza rinunciare a nulla.

Ad esempio, con 3 bit abbiamo la seguente tabella:

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

con incrementi di uno (e tenendo troppo pieno in considerazione) è equivalente a muoversi verso il basso una voce nella tabella, in entrambi i casi. Si noti che questo non funziona per quelli completano l'aritmetica, dal momento che i negativi sono disposti in ordine inverso.

è possibile dichiarare l'uint come volatile.

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top