我有一個巨大的數組,其中包含一個結構「瓷磚」。我編寫的程序是一個2D遊戲,我不希望不同的玩家(由不同的線程處理)將他們的位置同時寫入同一個圖塊,我想知道兩件事情。兩個線程可以同時安全地寫入數組中的兩個不同位置,並且是否有一種有效的方法來鎖定此數組中的一個索引?多線程結構數組可以同時寫入不同的索引嗎?
回答
是的,你可以在不同的線程同時寫入不同的位置。
做鎖定,您應該創建鎖定陣列,並使用一些簡單的散列技術選擇鎖定,基於位置被寫入。例如:
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盜取一個。
沒有內置的支持你想要做什麼。多個線程可以同時訪問同一個數組,但是您需要通過同步等方式自己處理數據一致性。因此,雖然可以實現每個索引鎖定(這與數據庫在事務中的操作類似),但我不確定這是您嘗試執行的正確方法。你爲什麼要用數組開始?
我認爲它應該具有我需要的快速訪問,並且由於它是2D遊戲,我可以使用X和Y座標作爲索引。 – Alle 2010-07-17 12:52:17
我相信你可以使用lock statement使代碼線程安全的,其訪問數組,並在線程之間共享。
可以使用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
結構轉換爲一類是能夠做到這一點。
- 1. 多個線程可以同時將數據寫入文件嗎?
- 2. 兩個線程可以寫入同一個數組的不同元素嗎?
- 3. 我可以從不同的MPI_Irecv寫入不同索引位置的相同緩衝區/數組嗎?
- 4. 同時寫入Lucene索引
- 5. 是否可以從多個線程寫入同一文件的不同部分?
- 6. 可以同時寫入/讀取同一個數據流嗎?
- 7. Google V8引擎可以在不同線程中的不同上下文中同時運行不同的Javascript嗎?
- 8. POST/PUT與返回的結構不同的結構可以嗎?
- 9. 可以從不同的線程多次檢查一個數組
- 10. 線程能否在不鎖定的情況下寫入相同結構數組的不同元素?
- 11. 多個線程可以加入相同的boost :: thread嗎?
- 12. 多個線程可以同時更新DynamoDB中的記錄嗎?
- 13. 可以多個線程操作相同的數據庫嗎?
- 14. 多個線程可以同時訪問共享內存嗎?
- 15. ASP.NET工作線程可以同時處理多個請求嗎?
- 16. android java從不同的線程同時讀取/寫入textview
- 17. 兩個線程可以同時訪問同步方法嗎?
- 18. 線程可以混合寫入值嗎?
- 19. 對有多個線程寫入相同索引的CUDA內核進行編碼?
- 20. numpy數組索引:列表索引和np.array索引給出不同的結果
- 21. Fabric和AppStore可以同時構建嗎?
- 22. 正在訪問TObjectList線程安全的不同索引嗎?
- 23. 從不同線程同時插入多個不鎖定表?
- 24. orientdb創建索引同時不能寫
- 25. 如果所有線程正在寫入不同的位置,多個線程是否可以同時寫入文件?
- 26. 你可以同時創建一個包含索引的表嗎?
- 27. 可以同時搜索PDF和Clearscan嗎?
- 28. 同時讀取/寫入線程
- 29. 我可以同時在mysql中插入2行或數組嗎
- 30. 兩個線程可以使用相同的線程程序嗎?
啊,謝謝:) 思想爲對象提供鎖定一個同樣大小的數組,但是這更有意義。 – Alle 2010-07-17 13:00:03
這樣做意味着我必須更改爲1維數組,但是,對不對? – Alle 2010-07-17 13:14:55
@Alle:原則是產生一個位置的散列。如果它是一維數組,那麼它就是'i%numLocks'的簡單問題,但這只是一個特例。如果你有一個2-D數組,那麼只要'i <0x10000',你就可以使用'hash(i << 16 + j)%numLocks'(其中'hash'是任何好的整數散列函數)。 – 2010-07-18 02:02:31