程序中有时会需要用到延迟计算。比如程序启动时计算尽可能少的内容可以加快启动速度等。
延迟计算有好处也有坏处。好处:按需计算不集中占用资源,用到的时候才进行计算,一些没用到的内容永不计算;坏处:假如需要用到时对象计算耗时过长,程序响应就会较慢,用户体验较差。所以用不用延迟计算要根据实际情况仔细掂量,适当的优化,做到真正的削峰填谷。
C#的lambada的延迟计算特性,延迟计算的代码包含在锁内,可是实际计算时却不在锁内,造成假锁。
实例:
class Program { private static readonly List<string> TextList = new List<string>(); private static readonly object SyncLock = new object(); static void Main() { new Thread(Add) { IsBackground = true }.Start(); new Thread(Remove) { IsBackground = true }.Start(); new Thread(Query) { IsBackground = true }.Start(); Console.ReadKey(); } private static void Query() { try { while (true) { var query = GetTexts(); Thread.Sleep(10); var x = query.ToArray(); Console.WriteLine(x.Length); } } catch (Exception e) { throw; } } private static IEnumerable<string> GetTexts() { lock (SyncLock) { return TextList.Select(item => item.ToString()); } } private static void Add() { while (true) { lock (SyncLock) { if (TextList.Count <= 0) { TextList.AddRange(Enumerable.Range(0, 100000).Select(item => item.ToString())); } } } } private static void Remove() { while (true) { lock (SyncLock) { if (TextList.Count > 0) { TextList.RemoveAt(0); } } } } }
多线程的方式对集合进行增删查,查采用lambda的延时计算。
运行上面的代码会报以下错误:
延迟加载不应该出锁,出锁了导致这样一个错误。
由以上可知,不要在锁中使用延时计算,即使想用这种写法也要在锁内完成计算。