Yes, you can write to different positions simultaneously from different threads.
To do the locking, you should create an array of locks, and use some simple hashing technique to choose a lock, based on the position being written. For instance:
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;
}
}
}
This avoids the need to create zillions of locks, but still keeps lock-contention to a minimum. You can set numLocks up or down, based on profiling. Keep it a power of two, though, for an efficient modulo computation.
One final minutiae: beware of aliasing effects. For instance, multiple-of-16 positions might happen to be very popular with your threads for some odd reason, in which case, contention will go through the roof. If this is the case, you'll need a stronger hash. Perhaps (uint)i.GetHashCode() % numLocks
will do, but I'm not sure what Int32.GetHashCode
does; it might just return the number itself. Failing this, you can steal one from Bob Jenkins.