C# 是否可以监视.Net';s的实习生人数?
我正在维护一个使用字符串在缓存中锁定值的遗留应用程序。它是这样做的:C# 是否可以监视.Net';s的实习生人数?,c#,.net,string-interning,C#,.net,String Interning,我正在维护一个使用字符串在缓存中锁定值的遗留应用程序。它是这样做的: object Cache(string key, Func<object> createObjToCache) { object result = Get(key); if (result == null) { string internKey = string.Intern(key); lock (internKey) { resul
object Cache(string key, Func<object> createObjToCache)
{
object result = Get(key);
if (result == null)
{
string internKey = string.Intern(key);
lock (internKey) {
result = Get(key);
if (result == null)
{
result = createObjToCache();
Add(key, result);
}
}
}
return result;
}
对象缓存(字符串键,Func createObjToCache)
{
对象结果=获取(键);
如果(结果==null)
{
string internekey=string.Intern(key);
锁(钥匙){
结果=获取(键);
如果(结果==null)
{
结果=createObjToCache();
添加(键、结果);
}
}
}
返回结果;
}
关于这个代码,我有两个问题。首先是string.Intern()线程安全吗?两个单独CPU上的两个线程(具有两个相同的字符串)是否可能返回不同的引用?如果不是的话,这是不是一个瓶颈,string.Intern是否会阻塞
其次,我担心这个应用程序可能会使用大量字符串作为键。我希望能够监视intern池用于存储所有这些字符串的内存量,但在.Net内存中找不到该内存的性能计数器。还有别的地方吗
注意:
我知道这个实现很糟糕。然而,在重新编写他们认为是关键的代码之前,我需要向管理层说明情况。因此,我可以使用事实和统计数据来说明它到底有多糟糕,而不是其他解决方案
另外,Get()和Add()不在原始代码中。我已经替换了原来的代码以保持这个问题的简单性。我们可以假设,如果使用相同或不同的键调用Add()两次,它不会失败。MSDN没有在
string.Intern
中提到线程安全,所以你是对的,如果两个线程同时调用Intern
一个新的键
,将会发生什么,这是非常不确定的。我想说“它可能会正常工作”,但这不是保证。没有任何保证。实现是extern
,因此查看实现意味着查看运行时本身
坦率地说,有太多理由不这样做,以至于很难对回答这些具体问题感到兴奋。我很想看看某种
字典
或ThreadSafeDictionary
(这里的对象
只是一个新对象()
,我可以用它来锁定),而没有与string.Intern
相关的所有问题。然后我可以a:查询大小,b:随心所欲地丢弃它,c:使用并行隔离容器等等。MSDN在string.Intern
中没有提到线程安全,所以你是对的,如果两个线程同时调用Intern
一个新的键
,将会发生什么,这是非常不确定的。我想说“它可能会正常工作”,但这不是保证。没有任何保证。实现是extern
,因此查看实现意味着查看运行时本身
坦率地说,有太多理由不这样做,以至于很难对回答这些具体问题感到兴奋。我很想看看某种字典
或ThreadSafeDictionary
(这里的对象
只是一个新对象()
,我可以用它来锁定),而没有与string.Intern
相关的所有问题。然后我可以a:查询大小,b:一时兴起丢弃它,c:拥有平行的隔离容器,等等
首先是string.Intern()线程安全吗
除非有什么改变(我关于这方面的信息很旧,我没有足够的好奇心来看看当前的实现),是的。然而,这是这个想法的唯一好处
事实上,这并不完全是一件好事string.Intern()
全局锁定,这是使其速度变慢的原因之一
其次,我担心这个应用程序可能会使用大量字符串作为键
如果缓存永远存在,那么无论你是否实习,这都是一个问题(如果内存使用量足够低,则不是问题)。在这种情况下,对正确的潜在问题采取错误的方法进行调查:
我希望能够监控实习生池用于存储所有这些字符串的内存量
如果它们没有被缓存,但仍然永远存在于缓存中,那么如果停止缓存,字符串本身的内存量仍然是相同的,而缓存的额外内存开销也不会真正成为问题
有几个原因可以解释为什么需要插入一个键,而且不是所有的都是坏的(如果被插入的字符串在应用程序的整个生命周期中都会定期出现,那么插入甚至可以减少内存使用),但这里的原因似乎是为了确保锁定的密钥与另一次尝试使用相同字符串时使用的实例相同
这可能是错误位置的线程安全性,如果Add()
的线程安全性不足以保证同时插入两个不同的键不会将其置于无效状态(如果Add()
不是显式线程安全的,那么它就不保证线程安全)
如果缓存是线程安全的,那么这可能是额外的线程安全,没有什么好的理由。由于已经创建了objToCache
,比赛将导致一个被扔掉,因此可以让他们比赛,并在收集一个前有两个objToCache
的短暂时间。如果没有,则MemoryCache.AddOrGetExisting
或ConcurrentDictionary.GetOrAdd
可以更好地处理此问题
首先是string.Intern()线程安全吗
除非有什么改变(我关于这方面的信息很旧,我没有足够的好奇心来查看当前的实现)