【发布时间】:2015-10-12 08:43:20
【问题描述】:
我想知道以下代码是否是线程安全的,我认为不是。我怎么可能让它线程安全?
基本上我有一个ConcurrentDictionary,它充当数据库表的缓存。我想每 10 秒查询一次数据库并更新数据库缓存。将有其他线程一直在查询该字典。
我不能只使用TryAdd,因为可能还有我已删除的元素。所以我决定不要搜索整个字典来更新、添加或删除。我只是重新初始化字典。请告诉我这是不是一个愚蠢的想法。
我担心的是,当我重新初始化字典时,当初始化发生时,查询线程将不再是线程安全的实例。出于这个原因,我在更新字典时使用了一个锁,但是我不确定这是否正确,因为锁中的对象发生了变化?
private static System.Timers.Timer updateTimer;
private static volatile Boolean _isBusyUpdating = false;
private static ConcurrentDictionary<int, string> _contactIdNames;
public Constructor()
{
// Setup Timers for data updater
updateTimer = new System.Timers.Timer();
updateTimer.Interval = new TimeSpan(0, 0, 10, 0).TotalMilliseconds;
updateTimer.Elapsed += OnTimedEvent;
// Start the timer
updateTimer.Enabled = true;
}
private void OnTimedEvent(Object source, System.Timers.ElapsedEventArgs e)
{
if (!_isBusyUpdating)
{
_isBusyUpdating = true;
// Get new data values and update the list
try
{
var tmp = new ConcurrentDictionary<int, string>();
using (var db = new DBEntities())
{
foreach (var item in db.ContactIDs.Select(x => new { x.Qualifier, x.AlarmCode, x.Description }).AsEnumerable())
{
int key = (item.Qualifier * 1000) + item.AlarmCode;
tmp.TryAdd(key, item.Description);
}
}
if (_contactIdNames == null)
{
_contactIdNames = tmp;
}
else
{
lock (_contactIdNames)
{
_contactIdNames = tmp;
}
}
}
catch (Exception e)
{
Debug.WriteLine("Error occurred in update ContactId db store", e);
}
_isBusyUpdating = false;
}
}
/// Use the dictionary from another Thread
public int GetIdFromClientString(string Name)
{
try
{
int pk;
if (_contactIdNames.TryGetValue(Name, out pk))
{
return pk;
}
}
catch { }
//If all else fails return -1
return -1;
}
【问题讨论】:
-
为什么需要重新初始化字典?你不能
Clear()它吗? -
当字典从不被并发访问时,为什么要使用并发字典?你是从其他地方写信给它的吗?
-
@usr 我从几个不同的线程同时访问它。
-
@Zapnologica - 您正在从多个线程中读取它?不是从多个线程写入?
-
@Zapnologica - 为什么要混合使用
static和非静态代码?
标签: c# multithreading locking concurrentdictionary