(C#) 使 Dictionary<ReaderWriterLockSlim> 的自动 GC 成为可能
(C#) make auto GC possible for Dictionary<ReaderWriterLockSlim>
我维护了一个 ReaderWriterLockSlim 对象的字典用于资源访问:(这里的示例代码很丑,只是让你明白我的目的)
static ConcurrentDictionary<string, ReaderWriterLockSlim> rwResourceLocks =
new ConcurrentDictionary<string, ReaderWriterLockSlim>();
并像这样使用:
if (ResourceStore.Exist("resourceID")) {
if (rwResourceLocks["resourceID"] == null) {
/* create a new lock in thread-safe way */
}
rwResourceLocks["resourceID"].EnderReadLock();
var rc = ResourceStore.GetResource("resourceID");
/* further use of rc... */
rwResourceLocks["resourceID"].ExitReadLock();
}
资源可以动态添加或删除,并且它们的生命周期是不可预测的(无法监控资源的删除),随着资源量的增长,rwResourceLocks 的大小也会增加,这将导致内存问题。有没有办法解决这个问题? (显然我不能简单地调用 rwResourceLocks.Clear() 来做到这一点)
我知道这有点复杂:(
您可以尝试使用 ConditionalWeakTable instead of a ConcurrentDictionary。 ConditionalWeakTable
当垃圾收集器收集到它的键时,它会自动从字典中删除一个值。
ConditionalWeakTable<object, ReaderWriterLockSlim> _locks;
if (ResourceStore.Exists("resourceID")) {
var rc = ResourceStore.GetResource("resourceID");
var lck = _locks.GetValue(rc, () => new ReaderWriterLockSlim());
lck.EnterReadLock();
// Use the resource here
lck.ExitReadLock();
}
我维护了一个 ReaderWriterLockSlim 对象的字典用于资源访问:(这里的示例代码很丑,只是让你明白我的目的)
static ConcurrentDictionary<string, ReaderWriterLockSlim> rwResourceLocks =
new ConcurrentDictionary<string, ReaderWriterLockSlim>();
并像这样使用:
if (ResourceStore.Exist("resourceID")) {
if (rwResourceLocks["resourceID"] == null) {
/* create a new lock in thread-safe way */
}
rwResourceLocks["resourceID"].EnderReadLock();
var rc = ResourceStore.GetResource("resourceID");
/* further use of rc... */
rwResourceLocks["resourceID"].ExitReadLock();
}
资源可以动态添加或删除,并且它们的生命周期是不可预测的(无法监控资源的删除),随着资源量的增长,rwResourceLocks 的大小也会增加,这将导致内存问题。有没有办法解决这个问题? (显然我不能简单地调用 rwResourceLocks.Clear() 来做到这一点)
我知道这有点复杂:(
您可以尝试使用 ConditionalWeakTable instead of a ConcurrentDictionary。 ConditionalWeakTable
当垃圾收集器收集到它的键时,它会自动从字典中删除一个值。
ConditionalWeakTable<object, ReaderWriterLockSlim> _locks;
if (ResourceStore.Exists("resourceID")) {
var rc = ResourceStore.GetResource("resourceID");
var lck = _locks.GetValue(rc, () => new ReaderWriterLockSlim());
lck.EnterReadLock();
// Use the resource here
lck.ExitReadLock();
}