2009-06-01 72 views
10

我想從多個線程增加一個無符號整數。C#多線程無符號增量

我知道Interlocked.Increment,但它不處理無符號整數。我可以使用lock(),但如果可能出於性能原因,我寧願不使用。

它是線程安全的,只是以正常的方式增加它?偶爾增加的數據丟失並不重要,因爲它僅用於統計數據。我不想要的是損壞的價值。

回答

-11
+7

這隻能確保對v可變的會立即寫回到內存中,而不是等待線程退出或寄存器中的值被移位。它不保護對現場的訪問,即兩個(或更多)線程可以讀取相同的值,遞增一次,然後寫回,從而有效地將值增加1. – 2009-06-01 12:42:49

+0

請閱讀上述要求以及 http: //msdn.microsoft.com/en-us/library/7a2f3ay4.aspx。 對於給定的情況就足夠了。 – Sesh 2009-06-01 15:00:23

+0

與Interlocked.Increment相比,性能如何變化?相同?更好? – jrista 2009-06-07 02:08:42

9

如果你真的需要全方位unsigned int型的(2^32 - 1),而不是一個有符號整數(2^231-1),你可以轉換爲64位整數(有一個Interlocked.Increment需要int64的重載),然後轉換回unsigned int。

30

你說你不想使用lock出於性能的原因 - 但你測試過嗎?一個無爭議的鎖(這可能是,它的聲音)是相當便宜。

當談到線程化(通常,但特別是線程化)時,我通常會選擇「明顯正確」,而不是「聰明並可能更好地執行」。

基準測試你的應用有無鎖定,看看你是否能夠注意到它們之間的差異。如果鎖定造成顯着差異,那麼確定使用狡猾的東西。否則,我只是堅持一個鎖。

一個你可能想要做的事情是使用Interlocked.Incrementint和只投它在必要時獲得uint,像這樣:

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 (uint) newValue; 
    } 

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

} 

輸出:

2147483647 
2147483648 
2147483649 

(換句話說,它沒有任何問題。)