我写了一个小数据库,其中使用率是95%。我一直在寻找瓶颈,出于好奇心想要比较可用锁定机制的速度:
在纯粹的单线程环境中,我只使用读取请求获得此结果:
无锁:1% 自旋锁:16% rwLock:60% 要完成的滴答声。
我知道RWLock在多线程环境中会看起来好多了,但是我不太清楚为什么只需要一个锁定阅读需要花费更多时间?
我写了一个小的自定义RW锁定,它比rwLock的性能提高了3倍,占总刻度的20%。
以下是代码:
class FastRWLock
{
private int _readers = 0;
private bool _isWriting = false;
private object _spinLock = new object();
private AutoResetEvent _notifier = new AutoResetEvent(false);
private bool needsNotify = false;
public void AquireReaderLock() {
if (_isWriting) {
lock (_spinLock) {
}
}
_readers++;
}
public void ExecuteWrite(Action a) {
if (_isWriting) {
lock (_spinLock) {//Only ends up here if another writer has already entered the following spinlock, thus, this one wont exite here until the previous write is done
}
}
try
{
_isWriting = true;
lock (_spinLock)//intention to write made public, idling until previous readers, that enqueued when another writeaction was active
{//probable deadlock?
if (_readers > 0) {
needsNotify = true;
_notifier.WaitOne();
needsNotify = false;
}
a.Invoke();
}
}
finally {
_isWriting = false;
}
}
public void ReleaseReaderLock() {
_readers--;
if (_readers < 1 && needsNotify) {
_notifier.Set();
}
}
}
这是一个可行的解决方案还是我冒着陷入僵局的风险?如果没有,标准RWLock还有什么能让它表现得更差?
答案 0 :(得分:1)
您需要使用lock
块之外的变量的易失性读写,您可能正在读取缓存值。
此外,您无法在_readers--
块之外的多线程环境中执行_readers++
或lock
。您需要使用Interlocked.Increment
和Interlocked.Decrement
可能还有其他问题,但是第一个跳到我身边的主要问题。
如果您修复了代码中的问题,我敢打赌您会看到更少的“性能提升”,因为我认为性能提升是由于代码中的错误导致您的版本不可靠使用。编写锁定原语很难正确完成。我建议尽可能使用内置类。