2010-07-17 85 views
1

我有一個巨大的數組,其中包含一個結構「瓷磚」。我編寫的程序是一個2D遊戲,我不希望不同的玩家(由不同的線程處理)將他們的位置同時寫入同一個圖塊,我想知道兩件事情。兩個線程可以同時安全地寫入數組中的兩個不同位置,並且是否有一種有效的方法來鎖定此數組中的一個索引?多線程結構數組可以同時寫入不同的索引嗎?

回答

2

是的,你可以在不同的線程同時寫入不同的位置。

做鎖定,您應該創建鎖定陣列,並使用一些簡單的散列技術選擇鎖定,基於位置被寫入。例如:

class TileArray 
{ 
    private static readonly int numLocks = 16; 
    private object[] locks = (from i in Range(0, numLocks) select new object()).ToArray(); 
    private Tile[] tiles = hugeTileArray(); 

    ... 

    public Tile this[int i] 
    { 
     get { return tiles[i]; } 
     set 
     { 
      lock (locks[i % numLocks]) 
       tiles[i] = value; 
     } 
    } 
} 

這樣可以避免需要創建大量的鎖,但仍然將鎖爭用保持在最低限度。您可以根據配置文件設置numLocks。儘管如此,仍然保持它的二次冪,以進行有效的模計算。

最後的細節:謹防鋸齒效應。例如,16個職位中的多個職位可能因爲某些奇怪的原因而在您的線程中非常受歡迎,在這種情況下,爭用將通過屋頂。如果是這種情況,你需要一個更強大的散列。也許(uint)i.GetHashCode() % numLocks會做,但我不知道Int32.GetHashCode做什麼;它可能只是返回數字本身。如果沒有這個,你可以從Bob Jenkins盜取一個。

+0

啊,謝謝:) 思想爲對象提供鎖定一個同樣大小的數組,但是這更有意義。 – Alle 2010-07-17 13:00:03

+0

這樣做意味着我必須更改爲1維數組,但是,對不對? – Alle 2010-07-17 13:14:55

+0

@Alle:原則是產生一個位置的散列。如果它是一維數組,那麼它就是'i%numLocks'的簡單問題,但這只是一個特例。如果你有一個2-D數組,那麼只要'i <0x10000',你就可以使用'hash(i << 16 + j)%numLocks'(其中'hash'是任何好的整數散列函數)。 – 2010-07-18 02:02:31

0

沒有內置的支持你想要做什麼。多個線程可以同時訪問同一個數組,但是您需要通過同步等方式自己處理數據一致性。因此,雖然可以實現每個索引鎖定(這與數據庫在事務中的操作類似),但我不確定這是您嘗試執行的正確方法。你爲什麼要用數組開始?

+0

我認爲它應該具有我需要的快速訪問,並且由於它是2D遊戲,我可以使用X和Y座標作爲索引。 – Alle 2010-07-17 12:52:17

0

我相信你可以使用lock statement使代碼線程安全的,其訪問數組,並在線程之間共享。

+0

我試過了,但我認爲它說Struct不是一個引用類型或類似的東西 – Alle 2010-07-17 12:52:52

+0

這也不能保護數組索引,這可能不是問題所要求的。 – Lucero 2010-07-17 15:17:54

1

可以使用Interlocked.CompareExchange函數來完成讀和不明確的使用鎖的安全寫。

public class Example 
{ 
    private Tile[] m_Array; 

    public Tile this[int index] 
    { 
    get { return Interlocked.CompareExchange(ref m_Array[i], null, null); } 
    set { Interlocked.CompareExchange(ref m_Array[i], value, m_Array[i]); } 
    } 
} 

當然,你將有你的Tile結構轉換爲一類是能夠做到這一點。

相關問題