何时在C#中使用锁定线程?

我有一个服务器,它处理多个传入的套接字连接,并创建2个不同的线程,以XML格式存储数据。

我几乎在每个名为asyncronously的事件处理程序和代码的不同部分的2个线程中使用lock语句来实现线程安全。 遗憾地使用这种方法我的应用程序显着减慢。

我试图完全不使用lock ,服务器执行速度非常快,即使文件存储似乎也在提升; 但程序因30秒-1分钟后我不理解的原因而崩溃。 工作的。

所以。 我认为最好的方法是使用较少的锁或只在必要的地方使用它。 因此,我有两个问题:

  1. 当我写入公共访问变量(C#列表)时,甚至当我从中读取时,是否需要锁定?

  2. 是否只需要在套接字处理程序或其他地方创建的异步线程中进行锁定?

有人可以给我一些关于如何操作的实用指南。 我这次不会发布整个代码。 发布大约2500行代码是没有意义的。

当我写入公共访问变量(C#列表)时,甚至当我从中读取时,是否需要锁定?

是的(即使你读过)。

是否只需要在套接字处理程序或其他地方创建的异步线程中进行锁定?

是。 只要代码访问共享的代码段,总是锁定。


这听起来好像你可能没有锁定单个对象,而是为所有锁定情况锁定一个东西

如果这样,通过创建单独的唯一对象放入智能离散锁中,这些对象一次只关联并锁定某些部分,这不会干扰其他部分中的其他线程。

这是一个例子:

 // This class simulates the use of two different thread safe resources and how to lock them // for thread safety but not block other threads getting different resources. public class SmartLocking { private string StrResource1 { get; set; } private string StrResource2 { get; set; } private object _Lock1 = new object(); private object _Lock2 = new object(); public void DoWorkOn1( string change ) { lock (_Lock1) { _Resource1 = change; } } public void DoWorkOn2( string change2 ) { lock (_Lock2) { _Resource2 = change2; } } } 

当没有交叉路口时,你是否曾坐在车上或红灯处的公共汽车上? 浪费时间,对吧? 锁就像一个完美的交通灯。 它总是绿色的,除非交叉路口有交通。

你的问题是“我花了太多时间在红灯等待交通。我应该只是运行红灯吗?或者甚至更好,我应该完全拆除灯光,只是让所有人在没有任何交叉口控制的情况下以高速公路的速度穿过交叉路口? “

如果您遇到锁定性能问题,那么删除锁定是您应该做的最后一件事。 你正准备等待红灯,因为交叉路口有交叉路口 。 如果没有争用,锁的速度非常快

在不消除交叉流量的情况下,您无法消除光线。 因此,最佳解决方案是消除交叉流量 。 如果锁永远不会争用,那么你永远不会等待它。 弄清楚为什么交叉流量在交叉路口花费了这么多时间; 不要移除光线,希望没有碰撞。 将有。

如果你不能这样做,那么添加更细粒度的锁有时会有所帮助 。 也就是说,也许你在城里的每条道路都聚集在同一个交叉路口。 也许您可以将其拆分为两个交叉点,以便代码可以同时在两个不同的交叉点中移动。

请注意, 使汽车更快 (获得更快的处理器)或缩短道路 (消除代码路径长度)通常会使问题在multithreading场景中变得更糟。 就像在现实生活中一样; 如果问题是僵局,那么购买更快的汽车并在较短的道路上驾驶它们会使他们更快地堵塞交通堵塞,但不会更快。

访问成员(读取或写入)时始终使用锁定。 如果您正在迭代一个集合,而另一个线程正在删除项目,那么事情很快就会出错。

建议是,您希望迭代集合,将所有项目复制到新集合,然后迭代副本。 即

 var newcollection; // Initialize etc. lock(mycollection) { // Copy from mycollection to newcollection } foreach(var item in newcollection) { // Do stuff } 

同样,只有在您实际写入列表时才使用锁定。

您在阅读时需要锁定的原因是:

假设您正在对一个属性进行更改,并且当线程处于锁定之间时,它已被读取两次。 在我们做出任何改变之前和之后,我们将得到不一致的结果。

我希望有帮助,

基本上这可以很简单地回答:

您需要锁定不同线程访问的所有内容。 如果关于阅读或写作,它实际上并不重要。 如果您正在读取并且另一个线程同时覆盖数据,则读取的数据可能会无效并且您可能正在执行无效操作。