Упрощение синтаксиса ReaderWriterLockSlim
Мне недавно пришлось использовать ReaderWriterLockSlim
синхронизировать доступ к нескольким ресурсам, которые совместно используются несколькими потоками. Делая это, я чувствовал, что с помощью ReaderWriterLockSlim
Это не так просто, особенно, когда вы должны использовать его в нескольких местах. У тебя должно быть try...finally
блоки и не забудьте открыть и закрыть замки. Во многих случаях я также обнаружил, что открываю блокировку записи и закрываю блокировку чтения вместо закрытия блокировки записи. Поэтому я попытался придумать более простой способ использования ReaderWriterLockSlim
, Это где я получил
class Locked<T>
{
private T _resource;
private ReaderWriterLockSlim _lock;
public Locked(T resource)
{
_resource = resource;
_lock = new ReaderWriterLockSlim();
}
public void Read(Action<T> ReadAction)
{
try
{
_lock.EnterReadLock();
ReadAction(_resource);
}
finally
{
_lock.ExitReadLock();
}
}
public void Write(Action<T> WriteAction)
{
try
{
_lock.EnterWriteLock();
WriteAction(_resource);
}
finally
{
_lock.ExitWriteLock();
}
}
}
Теперь, например, если нам нужно синхронизировать доступ к List<string>
это то, как мы делаем это, используя класс выше
public class Demo
{
private Locked<List<string>> _listOfString;
public Demo()
{
_listOfString = new Locked<List<string>>(new List<string>());
}
public void writeMethod(string value)
{
_listOfString.Write(list =>
{
list.Add(value);
});
}
public string readMethod(int index)
{
string value = null;
_listOfString.Read(list =>
{
value = list[index];
});
return value;
}
}
Как вы думаете, этот подход лучше? Есть ли недостатки или недостатки.
1 ответ
Я бы предпочел обернуть логику блокировки в IDisposable
и поместите код, который вы хотите заблокировать, используя блок, очень похожий на lock
заявление:
class DisposableLock : IDisposable
{
Action _exitLock;
public DisposableLock(Action exitLock)
{
_exitLock = exitLock;
}
public void Dispose()
{
_exitLock();
}
}
class ReadLock : DisposableLock
{
public ReadLock(ReaderWriterLockSlim slimLock)
: base(() => slimLock.ExitReadLock())
{
slimLock.EnterReadLock();
}
}
class WriteLock : DisposableLock
{
public WriteLock(ReaderWriterLockSlim slimLock)
: base(() => slimLock.ExitWriteLock())
{
slimLock.EnterWriteLock();
}
}
Вы бы использовали это так:
using(new ReadLock(_lock))
{
// ... your synchronized operation
}
using(new WriteLock(_lock))
{
// ... your synchronized operation
}