很少有关于锁的令人困惑的事情

时间:2010-03-01 19:54:00

标签: c# .net multithreading

5 个答案:

答案 0 :(得分:8)

  1. 在这种情况下,锁的范围是类本身的单个实例。这与跨越特定类的所有实例相反。你可以通过使lockThis静态来锁定所有实例TestThreading。这就是锁的“范围”的含义:它是适用于单个实例,还是适用于特定类型的每个实例。

  2. “锁定对象thisObject”只是意味着使用thisObject作为确定我们是否在锁中的对象。该术语并不表示我们“锁定”了lockThis对象。我认为你的估计是正确的。其他对象仍然可以从另一个线程访问lockThis,但是他们无法处理那个对象上的锁定所包围的代码。

  3. 由于我们互相回应,这里有更多信息:

    让我们采用您在上面概述的“房间和钥匙”类比,并针对每种可能性进行扩展。我们有几种不同的情况:

    1. 静态函数,静态锁定对象 - 这类似于拥有一个房间,只有一个密钥。
    2. 实例函数,静态锁定对象 - 这就像拥有几个共享相同密钥的房间......例如主密钥。
    3. 实例函数,实例锁定对象 - 这就像拥有几个房间,每个房间都有自己的钥匙......就像宿舍或酒店一样。
    4. 静态函数,实例锁定对象 - 不可能。您无法从静态上下文访问实例字段。
    5. 希望上述方案概述了这些方案如何协同工作。

      回应第二个回复

        

      我不确定你的意思是TestThreading.Function无法访问lockThis?!

      它无法访问有用的 lockThis。锁定在锁定完成时被抛弃的实例上的静态方法是无用的。在您设置的场景中,每次接近门时,锁定“放弃”一个新钥匙,并说“好吧,我接受我刚给你的钥匙......你可以进来”。在那种情况下,它太松散地守护着“房间”,让每个人都可以随时访问。换句话说,在第二个例子中没有理由甚至有一个锁定语句。这就像房间有一个动态增加的门数,只使用一次,其中有一个密钥贴在上面。无数人可以随时进入。你的代码和以下代码之间没有区别,真的(有,但是这样你可以有希望得到这个概念:

      public class TestThreading
      {
          private object lockThis = new object();
      
          public static void Function() 
          {
              lockThis = new object();
              lock (lockThis)
              {
                  // access something   
              }
          }
      }
      

      我在上面的例子中所做的基本上是扔掉并重新锁定锁然后才在门中使用它。那没用。你是对的,没有任何线程同步,从这个意义上说,我会说代码根本不起作用,因为锁的整个点是同步线程。

        

      如果lockThis是静态的,那么全部   TestThread实例将共享   同样的房间(又名锁),即使   TestThread.Function不是静态的。   假设我理解正确   现在,锁定一词就是指   到钥匙(因此锁不参考   房间?!用于打开   门?

      不,如果 Function 是静态的,那么所有TestThread实例将共享同一个房间,如果lockThis是静态的,则所有TestThread实例将共享相同的密钥

      lock (key)
      {
         // room
      }
      

      房间是在锁内执行的代码,而不是lockThis对象本身,这只是密钥。

        

      因此,如果我们假设lockThis是   static和TestThread.Function不是   static,然后是键/锁的范围   是所有TestThread实例,其中   表示所有TestThread实例   共享相同的密钥,因此当一个   TestThread实例打开了大门   它的房间使用这个键,另一个   实例将无法打开   他们的房间门直到第一次   实例发布那个密钥?

      是。

答案 1 :(得分:2)

为了说明锁定静态或非静态对象的不同,请考虑:

public class TestThreading
{
    private object lockThis = new object();
    private static object lockStatic = new object();
    private Stream UIStream;
    private List<int> calcStuff;

    public void DoStuff1()
    {
        lock (lockThis)
        {
            // Do stuff with calcStuff that is unique to this instance
            // it's okay to have different instances calculating their own stuff
        }
    }

    public void DoStuff2()
    {
        lock (lockStatic)
        {
            // Do stuff with the UI,
            // which you don't want multiple threads accessing at once
        }
    }
}

特别是在像

这样的情况下
var A = new TestThreading();
var B = new TestThreading();

((Action)(A.DoStuff1)).BeginInvoke(null,null); // These can go concurrently
((Action)(B.DoStuff1)).BeginInvoke(null,null); // just fine

((Action)(A.DoStuff1)).BeginInvoke(null,null); // These will have to wait
((Action)(A.DoStuff1)).BeginInvoke(null,null);

((Action)(A.DoStuff2)).BeginInvoke(null,null); // These will have to wait
((Action)(B.DoStuff2)).BeginInvoke(null,null);

答案 2 :(得分:1)

该段落所讨论的是代码具有锁定的能力,而不是锁定的持续时间(该文章称为锁定持续时间)。

答案 3 :(得分:1)

大卫莫顿的回答对我来说似乎是正确的,但为了更好的参考,请参阅此网站:Threading in C#这是C#中所有线程的绝佳资源,包括的示例在少数情况下做。非常清楚的IMO。

答案 4 :(得分:1)

a)因为TestThreading类的每个对象都有自己的“lockThis”对象,所以只有那个单独的对象才会在lock b / c的范围内,只有单个对象才能引用“lockThis”(b / c)它是私人的)

b)不,这意味着因为调用锁的TestThreading对象是唯一可以“锁定”关键区域的对象(再次,b / c它是私有的),“锁定对象lockThis”意味着你正在锁定使用lockThis私有引用类型的TestThreading对象。

例如,如果你写了这个:

public class TestThreading
 {
     // private System.Object lockThis = new System.Object();

     public void Function()
     {

         lock (this)
         {
            // Access thread-sensitive resources.
         }
     }
  }

单个对象不仅可以使用Function方法锁定对象,每个类都可以使用Function方法锁定对使用的TestThreading对象,b / c TestThreading对象可能至少是“内部”,如果不是“公开”。