C#锁和新手多线程问题

一些关于.NET中多线程的新手问题,我认为这将有助于强化我想吸收的一些概念 - 我已经阅读了几种多线程材料(包括Albahari电子书),但觉得我只需要一些问题的确认帮助将这些概念推向家庭

  • 锁范围保护共享代码区域 - 假设有一个线程正在执行一个方法,该方法会在循环中增加一个简单的整数变量x - 但是,这不会保护其他地方的代码,这些代码也可能会改变变量x,例如另一个线程上的另一个方法...

    由于这是潜在影响同一个变量的两个不同区域的代码,我们是否可以通过锁定两个区域的代码来解决这个问题? 如果你用不同的锁变量锁定了两个区域的代码,这不会保护变量是否正确?

  • 为了进一步说明这个例子,使用相同的锁变量,如果出于某种原因会发生什么情况,一个方法中的代码进入某个无限循环并且永不放弃锁变量 - 另一个方法中的第二个代码区域如何检测这个?

  • 锁变量的选择如何影响锁的行为? 我已经阅读了许多关于这个主题的文章,但似乎找不到明确的答案 - 在某些情况下,人们明确地使用一个对象变量专门用于此目的,其他时间人们使用lock(this),最后有时候我已经见过人们使用类型对象。

    锁变量的不同选择如何影响锁的行为/范围,以及在哪种情况下使用它们会有意义?

  • 假设你有一个包装在类中的哈希表,它暴露了add,remove,get和某种Calculate方法(比方说每个对象表示一个数量,并且这个方法将每个值相加),并且所有这些方法都被锁定 - 但是,一旦对一个对象在该集合可供其他代码使用并传递给应用程序的情况下,此对象(不是散列表)现在将位于围绕该类方法的锁范围之外..那么您可以保护对所采取的实际对象的访问/更新从散列表,这可能会干扰计算方法?
  • 感谢提供的任何启发式方法,这将有助于为我加强这些概念 - 谢谢!


    1)你是对的。 您必须使用相同的锁对象来保护两个不同区域的代码,例如增加变量x。

    2)这被称为死锁,是多线程编程的难点之一。 有些算法可以用来防止死锁,例如Bankers算法。

    3)某些语言使得锁定变得容易,例如在.Net中,您可以创建一个对象并将其用作共享锁。 这对于同步给定进程内的代码很有用。 Lock(this)只是将锁应用于所讨论的对象。 然而,尽量避免这种情况,而是创建一个私人对象并使用它。 锁定(this)会导致死锁情况。 下面的锁对象可能只是一个关键部分的包装。 如果你想跨越不同的进程保护资源,你需要一个更重的Mutex,这需要对内核对象进行锁定,而且代价很高,所以除非必须,否则不要使用。

    4)您还需要确保在那里应用锁定。 但是当人们在这个引用上调用方法时,他们确实会调用采用同步的方法。


    1)是的

    2)这是一个僵局

    3)你想要阻止的代码部分是你的类的实现细节。 由于现在外部代码可以锁定相同的对象并无意或恶意阻止您的代码,因此使用lock(this)lock(this.GetType())公开锁对象会造成麻烦。 锁对象应该是私有的。

    4)你的意思不是很清楚,你肯定不想直接暴露Hashtable。 只要把它作为课堂的私人领域,封装它。

    但是,使用线程安全地将您的类暴露给客户端代码的几率会随着您公开的方法和属性的数量而迅速下降。 您将很快到达只有客户端代码才能正确锁定的点。 当客户端代码保留属性值时,细粒度锁定会创建大量线程化比赛的机会。 说你返回的Count属性值。 在使用该值时(如在for循环中),Count属性可能已更改。 只有最仔细的设计才能避免这些陷阱,令人头疼。

    此外,细粒度锁定效率非常低,因为它不可避免地会在代码的最内部完成。 锁并不是那么昂贵,大约100个cpu周期,但它很快累计起来。 尤其是如果类对象在多个线程中没有实际使用,则会浪费精力。

    然后你没有选择,只能声明你的类不安全,并且客户端代码需要以线程安全的方式使用它。 也是这么多.NET类不是线程安全的核心原因。 这是线程难以正确处理的最大原因,程序员最不可能正确执行的是负责做出最困难的事情。

    链接地址: http://www.djcxy.com/p/11105.html

    上一篇: C# locks and newbie multithreading questions

    下一篇: Datasnap and SocketError