获取UI线程上的锁是一种不好的做法吗?例如,我有一个缓存对象,它被后台线程和UI线程修改。对缓存的任何修改都包含在锁中。伪代码如下:
public class Cache
{
private readonly Dictionary<string, IEnumerable<string>> _cache;
private readonly object _onCache = new object();
public Cache()
{
_cache = new Dictionary<string, IEnumerable<string>>();
}
//Called by worker threads
public void RefreshInBackground(IEnumerable<string> items, string key)
{
lock (_onCache)
{
_cache[key] = items;
}
}
//Called by UI thread.Does this lead to any issues since UI thread is waiting on a lock?
public void RefreshInForeground(IEnumerable<string> items, string key)
{
lock (_onCache)
{
_cache[key] = items;
}
}
}
当UI线程调用RefreshInForegound时,它必须等待锁定(可能),问题是,这是不好的做法,如果是,为什么?
谢谢, -Mike
答案 0 :(得分:3)
如果它工作得很好,我就不会改变它。
如果您有性能问题,那么您可以调整它。有些要改进的地方:
RefreshInForeground
并使用Task
,ThreadPool
,BackgroundWorker
等从UI运行RefreshInBackground
。Monitor
和try-finally
,添加timeout
。这仍然不是最佳选择,因为UI线程最多会在timeout
的持续时间内被阻止。还是比永远等待更好。ReaderWriterLockSlim
ConcurrentDictionary
- 无锁或无阻塞类答案 1 :(得分:1)
当UI线程调用RefreshInForegound时,它必须等待锁定(可能),问题是,这是不好的做法,如果是,为什么?
如果操作可能需要很长时间,则可能会出现问题,因为它会阻止UI。
如果使用相同锁定对象的所有操作都很短(例如示例中的简单字典设置器),我就不用担心了。
答案 2 :(得分:0)
对于字典,自.Net 4.0以来有ConcurrentDictionary
个类。参见
Dictionary as thread-safe variable
对于其他类型的线程安全集合,您可能会看到http://msdn.microsoft.com/en-us/library/dd287108.aspx
对于锁定问题,这不是一个坏习惯。 lock
关键字是在平凡的使用中管理并发的最方便的方法,但不是最优的。例如,如果您正在进行单写多次读取同步,ReaderWriterLock
可能会更好。