我有一个属性
public ObservableCollection<string> Name
{
get
{
return _nameCache;
}
}
_nameCache由其他类方法中的多个线程更新。更新由锁定保护。问题是:我应该在return语句中使用相同的锁吗?不会使用锁导致竞争条件?
答案 0 :(得分:1)
是的,你应该。如果不添加锁,则可能不会返回_nameCache的最新值。
public ObservableCollection<string> Name
{
get
{
lock (_yourLockObject)
{
return _nameCache;
}
}
}
答案 1 :(得分:1)
这取决于更新的含义。
如果你的意思是修改了引用,即_nameCache = newvalue;
,那么就像马克所说的那样,是的,你应该(使用相同的锁),不,你不会得到竞争条件。
但是,如果您的意思是将项添加到_nameCache引用的实例中并将其删除,那么您将不需要在返回时锁定(因为引用本身永远不会更改)。但是,在检索它之后你必须要小心如何阅读它 - 理想情况下,你应该在调用它的任何方法之前使用相同的锁。
要么,或者您可以使用事件模型来通知新项目等,如果您需要做的就是跟踪更改 - 因为事件将在当前锁定集合的线程上引发。< / p>
如果这不合适(因为你总是通过索引器或其他方式获取元素),那么你总是可以通过这个属性返回一个ObservableCollection的副本 - 即return new ObservableCollection<string>(_nameCache);
。这将使属性的返回值短暂,但让任何调用者都可以自由枚举和索引而不必担心其他线程的状态损坏。
答案 2 :(得分:0)
是的,您可以使用相同的锁定对象。我假设您有一个声明的变量,例如以下锁定变量:private object _lock = new object();
如果是这样,您可以像下面的代码块一样使用_lock对象。
public ObservableCollection<string> Name
{
get
{
lock(_lock)
{
return _nameCache;
}
}
}
如果在多线程试图访问_nameCache的情况下没有实现锁定,则可能会收到一个不在当前调用此属性的上下文中的值。所以,如果多个线程正在访问相同的类memeber,例如您在上面概述的属性,则必须实现同步(锁定)。
享受!