我有一个.NET 4 WCF服务,它维护一个线程安全的,内存中的对象字典缓存(SynchronizedObject)。我想提供安全的并发访问来读取和修改集合中的集合和对象。使用读写器锁可以安全地修改对象和缓存。
我遇到了提供对缓存中对象的读访问权的问题。我的Read方法返回一个SynchronizedObject,但我不知道如何在WCF序列化SynchronizedObject时优雅地确保没有其他线程正在修改对象。
我尝试将Read return子句放在read-lock中,并在自定义XmlObjectSerializer中设置断点。当调用XmlObjectSerializer :: WriteObject(Stream,object)方法时,SynchronizedObject上不会保持读锁定。
我特别关注以下情况:
我看到两个选项:
我还有其他选择吗?我该如何实现线程安全的Read方法?
我在下面提供了一个虚拟服务,用于更明确的引用:
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();
}
}
答案 0 :(得分:0)
新答案
根据您的新信息和更清晰的场景,我相信您希望使用类似于函数式编程的不变性功能。不是序列化可以更改的对象,而是创建一个其他线程无法访问的副本,然后对其进行序列化。
以前(没有价值)回答
来自http://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim.enterwritelock.aspx:
如果其他线程已进入锁定状态 在读模式下,一个调用的线程 EnterWriteLock方法阻塞直到 那些线程已经退出读取模式。 有线程等待的时候 进入写模式,附加线程 试图进入阅读模式或 可升级模式块直到全部 线程等待进入写入模式 要么超时要么写入 模式,然后退出。
因此,您需要做的就是在ModifyObject()中调用EnterWriteLock和ExitWriteLock。您尝试确保同时具有读锁定和写锁定实际上是阻止代码工作。