【发布时间】:2026-02-10 00:35:01
【问题描述】:
下面的代码将从网站调用,因此非静态类中的静态字典对象需要是线程安全的。基本上,代码的目的是封装逻辑并维护存储在 CounterContainer 实例中的 perfmon 计数器的生命周期。构造函数被称为传入instanceName。构造函数需要检查该 instanceName 的 CounterContainer 是否已定义并存储在字典中。如果是这样,它可以(并且必须)使用该实例。如果不是,它会创建 CounterContainer 的实例,将其存储在字典中,然后使用该实例。要使用的 CounterContainer 的实例存储在一个非静态成员中,因此从那时起就是线程安全的。
作为使用静态字典的唯一位置是在构造函数中,我觉得在访问字典期间锁定字典是安全的吗?这是否会在以后导致任何不可预见的问题,例如阻塞/死锁?我什么都看不到,但过去真的没有必要过多地考虑这种事情。
我也考虑过 lock(this): 但我认为这不会起作用,因为它只会锁定正在创建的 PerformanceCounters 实例,而不是底层静态字典(所以不会是线程安全的)。
namespace ToolKit
{
using System;
using System.Diagnostics;
using System.Collections.Generic;
public class PerformanceCounters : IPerformanceCounters
{
private static Dictionary<string, CounterContainer> _containers = new Dictionary<string, CounterContainer>();
private CounterContainer _instanceContainer;
public PerformanceCounters(string instanceName)
{
if (instanceName == null) throw new ArgumentNullException("instanceName");
if (string.IsNullOrWhiteSpace(instanceName)) throw new ArgumentException("instanceName");
// Is this the best item to lock on?
lock (_containers)
{
if (_containers.ContainsKey(instanceName))
{
_instanceContainer = _containers[instanceName];
return;
}
_instanceContainer = new CounterContainer(instanceName);
_containers.Add(instanceName, _instanceContainer);
}
}
public void Start()
{
_instanceContainer.AvgSearchDuration.Start();
}
public void FinishAndLog()
{
_instanceContainer.SearchesExecuted.Increment();
_instanceContainer.SearchesPerSecond.Increment();
_instanceContainer.AvgSearchDuration.Increment();
}
}
}
【问题讨论】:
-
你考虑过使用 ConcurrentDictionary 类吗?那么您就不必担心了 - 也可能与这个问题重复:*.com/questions/440957/…
-
@BrokenGlass:对不起,我错过了,是的,它们的情况几乎相同。直到 ConcurrentDictionary 类也被提出作为对此的回应时才听说过。
标签: c# multithreading thread-safety