目录:
// 被 Monitor 保护的队列
private Queue<T> m_inputQueue = new Queue<T>();
// 给 m_inputQueue 加锁,并往 m_inputQueue 添加一个元素
public void Enqueue(T qValue)
{
// 请求获取锁,并阻塞其他线程获得该锁,直到获得锁
Monitor.Enter(m_inputQueue);
try
{
m_inputQueue.Enqueue(qValue);
}
finally
{
// 释放锁
Monitor.Exit(m_inputQueue);
}
}
lock 是语法糖,是对Monitor的Enter和Exit的一个封装。
lock (m_inputQueue) {} 等价于
bool __lockWasTaken = false;
try
{
System.Threading.Monitor.Enter(m_inputQueue, ref __lockWasTaken);
}
finally
{
if (__lockWasTaken) System.Threading.Monitor.Exit(m_inputQueue);
}
private readonly object balanceLock = new object();
private Queue<T> m_inputQueue = new Queue<T>();
public void Enqueue(T qValue)
{
lock (balanceLock)
{
m_inputQueue.Enqueue(qValue);
}
}
private static object _iBlockPortLockObj = new object();
private static IBlockPort _iBlockPort;
/// <summary>
/// 卡口
/// </summary>
/// <returns></returns>
public static IBlockPort CreateBlockPort()
{
if (_iBlockPort == null)
{
lock (_iBlockPortLockObj)
{
if (_iBlockPort == null)
{
string className = AssemblyName + "." + db + "BlockPort";
_iBlockPort = (IBlockPort)Assembly.Load(AssemblyName).CreateInstance(className);
}
}
}
return _iBlockPort;
}
public abstract class AbstractCache<T> where T : ICloneable
{
protected int queenLength = 30; // 保持队列的最大长度,主要可能考虑内存
/// <summary>
/// 过车缓存列表
/// </summary>
public List<T> listCache { get; set; }
protected object _lockObj = new object();
/// <summary>
/// 初始化或重置缓存列表
/// </summary>
protected void RefreshListCache()
{
lock (_lockObj)
{
if (listCache == null)
{
listCache = new List<T>();
}
else
{
listCache.Clear();
}
}
}
/// <summary>
/// 添加新的数据进队列,后续考虑做成环形队列减少开销
/// </summary>
/// <param name="list"></param>
protected void AddListToCache(List<T> list)
{
lock (_lockObj)
{
if (listCache == null) return;
listCache.InsertRange(0, list);
if (listCache.Count > queenLength)
{
listCache.RemoveRange(queenLength, listCache.Count - queenLength);
}
}
}
/// <summary>
/// 移除并返回过车缓存队列的最后一个元素
/// </summary>
/// <returns></returns>
public T DequeueLastCar()
{
T res = default;
lock (_lockObj)
{
if (listCache != null && listCache.Count > 0)
{
int lastIndex = listCache.Count - 1;
res = (T)listCache[lastIndex].Clone();
listCache.RemoveAt(lastIndex);
}
}
return res;
}
}
/// <summary>
/// 添加新的数据进队列,后续考虑做成环形队列减少开销
/// 清空、添加、取出一个数据,都需要加锁,但是由于添加的数据是从海康那边拿过来的,可能需要几秒的时间,
/// 可能会导致这样的结果:线程 A 查数据库(持续几秒)-> 线程 B 执行清空队列操作 -> 线程 A 将数据添加到队列
/// 因此将,锁直接移动到 lock {线程 A 查数据库、将数据添加到队列}
/// </summary>
/// <param name="list"></param>
protected void AddListToCache(List<T> list)
{
if (listCache == null) return;
listCache.InsertRange(0, list);
if (listCache.Count > queenLength)
{
listCache.RemoveRange(queenLength, listCache.Count - queenLength);
}
}
CancellationTokenSource source = new CancellationTokenSource();
/// <summary>
/// 定时获取 xx 数据
/// </summary>
public void GetPassCarInterval()
{
Task.Factory.StartNew(() =>
{
while (!source.IsCancellationRequested)
{
if (!string.IsNullOrWhiteSpace(xx))
{
lock (_lockObj)
{
// 从数据库获取数据
var list = GetPassCarInfo.GetLastBlockPortCarRecordBy(xx);
AddListToCache(list);
}
}
AutoReset.WaitOne(Common.GetDataTimespan);
}
}, TaskCreationOptions.LongRunning);
}
C# 应用 - 多线程 7) 处理同步数据之 Synchronized code regions (同步代码区域): Monitor 和 lock
原文:https://www.cnblogs.com/MichaelLoveSna/p/14507507.html