首先,您可能不需要任何锁。使用 CPU 以原子方式处理每次读取和写入的类型的数组进行读取和写入本身是线程安全的(但您可能需要放入内存屏障以避免过时的读取)。
也就是说,就像x = 34
整数是线程安全的,但x++
不是,如果您的写入依赖于当前值(因此是读取和写入),那么这不是线程安全的。
如果您确实需要锁,但不想要多达 50 个,则可以进行条带化。首先设置你的条带锁(我将使用简单的锁而不是ReaderWriterSlim
较小的示例代码,同样的原则适用):
var lockArray = new object[8];
for(var i =0; i != lockArray.Length; ++i)
lockArray[i] = new object();
然后当你去使用它时:
lock(lockArray[idx % 8])
{
//operate on item idx of your array here
}
这是一个锁的简单性和大小与每个元素的一个锁的内存使用之间的平衡。
如果一个元素上的操作依赖于另一个元素的操作,如果您需要调整数组的大小,或者您需要拥有多个锁的任何其他情况,则会出现很大的困难。总是以相同的顺序获取锁可以避免很多死锁情况(因此没有其他需要多个锁的线程会尝试获取您已经拥有的锁而持有您需要的锁),但是您需要非常小心这些案例。
您还想确保,如果您正在处理索引 3 和索引 11,则避免两次锁定对象 3(我想不出这种特定的递归锁定会出错的方法,但为什么不避免它呢?而不是必须证明它是递归锁定是安全的情况之一?)