List线程安全问题

hhhhha123 2020-06-15 04:27:26
List存了若干个对象,通过多线程长连接Socket的高并发心跳包更新对象状态(每个对象一个Socket,分别更新),经常需要Find或者FindAll或者for循环等进行修改对象操作对象,偶尔有List的ADD,Remove等操作,哪些地方需要lock?
...全文
618 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaoxiangqing 2020-06-18
  • 打赏
  • 举报
回复
用ConcurrentDictionary就行了
LionGod 2020-06-18
  • 打赏
  • 举报
回复
你要做到数据同步的效果就可以了,不能够出现删除后找不到这个对象,或是Null的问题
github_36000833 2020-06-18
  • 打赏
  • 举报
回复
从性能开销来说,加锁本身很快。当出现竞态时,性能才'大幅'下降(这里的'大幅'是相对非竞态加锁而言)。 比如List移除一个元素,List需要把目标元素移除后,把后续数据都往前挪一个位置。 对此类操作,加锁的过程就会相对的长,更容易招致出现竞态(即多个操作争相下锁,互相竞争)。
github_36000833 2020-06-18
  • 打赏
  • 举报
回复
引用 16 楼 hhhhha123 的回复:
...就是假如为了性能...
List数据结构的Find,Remove的复杂度是O(n),而Dictionary数据结构的复杂度是O(1)。 过于简单的说,当你有2000个连接,Find,Remove操作Dictionary的算法效率高2000倍。
hhhhha123 2020-06-18
  • 打赏
  • 举报
回复
谢谢各位
hhhhha123 2020-06-18
  • 打赏
  • 举报
回复
引用 11 楼 以专业开发人员为伍 的回复:
[quote=引用 楼主 hhhhha123 的回复:]经常需要Find或者FindAll或者for循环等进行修改对象操作对象,偶尔有List的ADD,Remove等操作,哪些地方需要lock?
就是这些操作需要lock,例如
lock(myList)
    return FindAll(myList, .......);
这类底层操作需要整体 lock。[/quote] 还有个问题,就是假如为了性能都不做lock,会产生什么错误和后果?(可以接受脏读,基本没有同时操作同一个对象的时候,ADDRemove的概率也很小,假如报错try、catch能捕获也行,只要不把系统弄崩溃就行)
  • 打赏
  • 举报
回复
lock 是个性能瓶颈,所以通常要尽可能对“细节”进行同步,而不是过多从高层对大对象进行死锁。因此并发多线程设计方面更加体现了一种“哲学思维”方式,也就是注重实证的方式、通过系统自测来确定“相对的”是非概念,而不是基于外来的所谓概念来评判绝对的是非概念。通常我们都会写一些测试,例如
Task[] tasks = ........;
await Task.WhenAll(tasks);
Debug.Assert(checkResults(),"系统并发操作异常“);
而且每天会重复几百遍,比如说你中午吃饭的时候就可以让几十个测试用例重复实例化、且并行运行几万个测试,然后看最后的断言是否能发现是一亿分之一的数据不一致性。

编程绝不是靠别人灌输什么“理论”而决定设计的好坏。要靠自己长期写测试。
  • 打赏
  • 举报
回复
引用 1 楼 hhhhha123 的回复:
多线程修改同一个对象的不同属性


修改队列中某一个对象的属性,不是 lock 队列,而是 lock 找到的对象。
  • 打赏
  • 举报
回复
引用 楼主 hhhhha123 的回复:
经常需要Find或者FindAll或者for循环等进行修改对象操作对象,偶尔有List的ADD,Remove等操作,哪些地方需要lock?


就是这些操作需要lock,例如
lock(myList)
return FindAll(myList, .......);
这类底层操作需要整体 lock。
正怒月神 2020-06-16
  • 打赏
  • 举报
回复
msdn已经给你推荐了 线程安全集合 •ConcurrentQueue •ConcurrentStack •ConcurrentBag : •BlockingCollection : •ConcurrentDictionary 你自己选择就好了。 至于一定要用list,那么就自己Lock
wanghui0380 2020-06-16
  • 打赏
  • 举报
回复
先脱离你的限定,直接从你的原始需求聊 心跳对应session--------在通行的IT世界里session用啥呢?当然第一眼就是缓存 你的要求可以是Cache,微软给你的MemoryCache就是线程安全的,同时你也可省掉一些操作(比如延长生存时间,自动移除过期)
assky124 2020-06-16
  • 打赏
  • 举报
回复
System.Collections.Concurrent 这里面有几个线程安全的集合
  • 打赏
  • 举报
回复
增删改,每个动作都要加锁
xian_wwq 2020-06-16
  • 打赏
  • 举报
回复
引用 楼主 hhhhha123 的回复:
List存了若干个对象,通过多线程长连接Socket的高并发心跳包更新对象状态(每个对象一个Socket,分别更新),经常需要Find或者FindAll或者for循环等进行修改对象操作对象,偶尔有List的ADD,Remove等操作,哪些地方需要lock?
凡是需要原子操作的,都加上lock
Bridge_go 2020-06-15
  • 打赏
  • 举报
回复
只用list,基本都要加锁,Find其实也是在for循环
北京.NET 2020-06-15
  • 打赏
  • 举报
回复
接收到更新放入队列ConcurrentQueue再进行处理
hhhhha123 2020-06-15
  • 打赏
  • 举报
回复
引用 2 楼 github_36000833 的回复:
List不适合这种情况。 用Dictionary数据结构,比如ConcurrentDictionary。
假如只能用List呢
github_36000833 2020-06-15
  • 打赏
  • 举报
回复
List不适合这种情况。
用Dictionary数据结构,比如ConcurrentDictionary。
hhhhha123 2020-06-15
  • 打赏
  • 举报
回复
多线程修改同一个对象的不同属性

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧