C# 静态getter应该是线程安全的吗
我想知道这个类是否是线程安全的 我可以访问C# 静态getter应该是线程安全的吗,c#,design-patterns,C#,Design Patterns,我想知道这个类是否是线程安全的 我可以访问货币属性的getter而不执行锁定吗 我是否应该在GetLiveExchangeRates()方法中锁定对Currences属性的访问 public class CurrencyManager { public static List<CurrencyModel> Currencies { get; private set; } private static readonly object LockObj = new obje
货币
属性的getter而不执行锁定吗
我是否应该在GetLiveExchangeRates()
方法中锁定对Currences
属性的访问
public class CurrencyManager
{
public static List<CurrencyModel> Currencies { get; private set; }
private static readonly object LockObj = new object();
public CurrencyManager()
{
Currencies = new List<CurrencyModel>();
}
public static void GetLiveExchangeRates()
{
lock (LockObj)
{
Currencies = GetSomeFooLiveDataFromInternet();
}
}
}
公共类CurrencyManager
{
公共静态列表货币{get;private set;}
私有静态只读对象LockObj=新对象();
公共货币经理()
{
货币=新列表();
}
公共静态void GetLiveExchangeRates()
{
锁(LockObj)
{
货币=从Internet()获取一些愚蠢的数据;
}
}
}
编辑
您将如何重构它?如果您必须坚持使用静态类,我将如下重构该类:
public class CurrencyManager
{
private static readonly IEnumerable<CurrencyModel> currencies = Enumerable<CurrencyModel.Empty();
private static readonly object LockObj = new object();
public static void RefreshLiveExchangeRates()
{
lock (LockObj)
{
CurrencyManager.currencies = GetSomeFooLiveDataFromInternet();
}
}
public static IEnumerable<CurrencyModel> GetCurrencies()
{
return CurrencyManager.currencies;
}
}
消费者(视图模型/控制器等)
公共类MyController
{
私人可数流动利率;
公共MyController()
{
//实例一个新服务;或者通过构造函数作为依赖项提供它
var currencyService=new currencyService();
this.currentRates=currencyService.GetLiveExchangeRates();
}
}
然后,您的消费类将使用它从服务获取的集合。如果它愿意,它可以将该集合传递给依赖它的其他对象。当您觉得集合过时时,可以从服务中重新获取它们。此时,您可能不需要执行任何锁定,因为只有使用者可以使用该属性,并且可以控制何时可以更改该属性。这允许多个实例查询最新的汇率,而不必进行锁定,并让每个人排队接收汇率
理想情况下,我希望看到它作为依赖项通过构造函数传入,隐藏在接口后面,在需要时刷新速率。因此,我不会在构造函数中获取速率,而是在需要时懒洋洋地获取它们。这将允许您异步完成工作(假设您的实际实现是异步的)
编辑
如果出于缓存目的将集合存储在静态类中,则可以将集合存储在服务中,并始终返回集合。只有在清除缓存时,才会返回一组新的汇率
public class CurrencyService
{
private static IEnumerable<CurrencyModel> currencyRates;
private static object ratesLock = new object();
public IEnumerable<CurrencyModel> GetLiveExchangeRates()
{
if (currencyRates == null)
{
lock (ratesLock)
{
currencyRates = GetSomeFooLiveDataFromInternet();
}
}
return currencyRates;
}
public void ClearRates()
{
currencyRates = null;
}
}
公共类货币服务
{
私有静态可数货币汇率;
私有静态对象ratesLock=新对象();
公共IEnumerable GetLiveExchangeRates()
{
if(currencyRates==null)
{
锁(速率锁)
{
currencyRates=从Internet()获取一些愚蠢的数据;
}
}
回报率;
}
公共收费
{
currencyRates=null;
}
}
这或多或少是一个实现变更。您的controller/viewmodel将继续点击
GetLiveExchangeRates()
,但它只会从您的外部服务获取一次。每次之后,它都会返回缓存。您只需支付一次锁定费,然后当其他对象同时访问您的服务时,您不再支付锁定费。尝试使用单例模式。这是错误代码。由于这个bug,线程不安全。当另一个线程创建一个新实例时,不会发生什么好事。好吧,假设没有人创建一个新实例?@dotctor Singleton如何帮助线程安全?实例构造函数为什么更改静态成员?
public class MyController
{
private IEnumerable<CurrencyModel> currentRates;
public MyController()
{
// Instance a new service; or provide it through the constructor as a dependency
var currencyService = new CurrencyService();
this.currentRates = currencyService.GetLiveExchangeRates();
}
}
public class CurrencyService
{
private static IEnumerable<CurrencyModel> currencyRates;
private static object ratesLock = new object();
public IEnumerable<CurrencyModel> GetLiveExchangeRates()
{
if (currencyRates == null)
{
lock (ratesLock)
{
currencyRates = GetSomeFooLiveDataFromInternet();
}
}
return currencyRates;
}
public void ClearRates()
{
currencyRates = null;
}
}