У меня есть служба .NET 4 WCF, которая поддерживает поточно-ориентированный кэш-память объектов в памяти (SynchronizedObject).Я хочу обеспечить безопасный параллельный доступ для чтения и изменения как коллекции, так и объектов в коллекции.Безопасное изменение объектов и кэша может быть выполнено с помощью блокировок чтения-записи.
У меня проблемы с предоставлением доступа для чтения к объекту в кэше.Мой метод Read возвращает SynchronizedObject, но я не знаю, как элегантно убедиться, что никакие другие потоки не модифицируют объект, пока WCF сериализует SynchronizedObject.
Я попытался поместить предложение Read return внутри блокировки чтения иустановка точки останова в пользовательском XmlObjectSerializer.Когда вызывается метод XmlObjectSerializer :: WriteObject (Stream, object), блокировка чтения не удерживается в SynchronizedObject.
Меня особенно касается следующий сценарий:
- Поток A вызывает чтение (int).Выполнение продолжается только после оператора return.К этому моменту, наконец, также был выполнен, и блокировка чтения на SynchronizedObject была снята.Выполнение потока A. прерывается.
- Поток B вызывает Modify (int) для того же идентификатора.Блокировка записи доступна и получена.В какой-то момент между получением блокировки записи и ее снятием поток B прерывается.
- Поток A перезапускается и сериализация продолжается.Поток B имеет блокировку записи для того же SynchronizedObject и находится в середине некоторого критического раздела, но Поток A читает состояние SynchronizedObject и, таким образом, возвращает потенциально недопустимый объект вызывающей стороне Read (int).
Я вижу два варианта:
- Поддерживать пользовательский XmlObjectSerializer, который захватывает блокировку чтения перед вызовом метода base.WriteObject (Stream, object) и освобождает его после.Мне не нравится эта опция, потому что подклассификация и переопределение функции сериализации каркаса для выполнения определенного действия, если объект для сериализации соответствует определенному типу, пахнет для меня.
- Создание глубокой копии SynchronizedObjectв методе Read, пока удерживается блокировка чтения, снимите блокировку и верните глубокую копию.Мне не нравится эта опция, потому что будет много подклассов SynchronizedObject, для которых мне потребуется реализовать и поддерживать правильные глубокие копиры, а глубокие копии могут быть дорогими.
Какие другие опции делаютЯ имею?Как мне реализовать потокобезопасный метод чтения?
Я предоставил фиктивную службу ниже для более явных ссылок:
public class Service : IService
{
IDictionary<int, SynchronizedObject> collection = new Dictionary<int, SynchronizedObject>();
ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();
public SynchronizedObject Read(int id)
{
rwLock.EnterReadLock();
try
{
SynchronizedObject result = collection[id];
result.rwLock.EnterReadLock();
try
{
return result;
}
finally
{
result.rwLock.ExitReadLock();
}
}
finally
{
rwLock.ExitReadLock();
}
}
public void ModifyObject(int id)
{
rwLock.EnterReadLock();
try
{
SynchronizedObject obj = collection[id];
obj.rwLock.EnterWriteLock();
try
{
// modify obj
}
finally
{
obj.rwLock.ExitWriteLock();
}
}
finally
{
rwLock.ExitReadLock();
}
}
public void ModifyCollection(int id)
{
rwLock.EnterWriteLock();
try
{
// modify collection
}
finally
{
rwLock.ExitWriteLock();
}
}
}
public class SynchronizedObject
{
public ReaderWriterLockSlim rwLock { get; private set; }
public SynchronizedObject()
{
rwLock = new ReaderWriterLockSlim();
}
}