代码之家  ›  专栏  ›  技术社区  ›  Dark Star1

锁有多深?

  •  9
  • Dark Star1  · 技术社区  · 15 年前

    我有以下代码:

                locker = new object();
            lock (locker)
            {
                for (int i = 0; i < 3; i++)
                     ver_store[i] = atomic_Poll(power);                
            }
    

    我只是在漫游,考虑到锁内的功能访问一些全局资源(其中有一个开放的套接字),对象内的所有全局资源是否也被锁定。(我知道,访问这些相同变量的任何其他函数也必须对它们实现锁,锁机制才有效。我只是还没来得及把它们锁起来。)

    7 回复  |  直到 12 年前
        1
  •  11
  •   Peter Lillevold Rene    15 年前

    lock语句不“lock code”或任何位于大括号pre-se之间的资源。

    我发现最好从线程的角度理解锁(毕竟,线程场景是您需要考虑锁的时候)。

    给出你的样本代码

    10  locker = new object();
    11  lock (locker)
    12  {
         ...
    15  }
    

    当线程x到达第10行时,将创建一个新对象,在第11行,将获取该对象的锁。线程x继续执行块中的任何代码。

    现在,当线程x在块的中间时,线程y到达第10行。你看,一个新的对象被创建了,因为它是由线程Y创建的,所以这个对象上当前没有获得任何锁。因此,当线程Y达到11时,它将成功获取对象上的锁,并继续与线程X同时执行该块。

    这就是锁应该防止的情况。那么该怎么办呢? 制作更衣室 共享对象 .

    01  static object locker = new object();
    
        ...
    
    11  lock (locker)
    12  {
         ...
    15  }
    

    现在,当线程x到达第11行时,它将获取锁并开始执行块。当线程Y到达第11行时,它将尝试获取与线程X相同的对象上的锁。由于此对象已被锁定,线程Y将等待直到释放锁。从而防止代码块的并发执行,从而保护该代码使用的任何资源被并发访问。

    注意:如果系统的其他部分应该围绕相同的资源进行序列化,那么它们都必须尝试锁定相同的共享锁对象。

        2
  •  4
  •   sharptooth    15 年前

    锁只影响锁语句体中的代码。作为参数传递的对象充当唯一标识符,它不会在内部以任何方式受到影响。

        3
  •  3
  •   Community Michael Schmitz    7 年前

    这非常简单——lock语句中的lock锁代码。如果您在代码中的其他地方使用这些资源,则该锁不会覆盖它们。

    有些类上有机制,因此可以锁定多个位置-例如 Hashtable's Syncroot property . 这是有用的 questionable though . 一 nice discussion about it is on SO .

    最好的办法是用一个内部锁定机制将这个逻辑封装在自己的类中,并确保应用程序只使用这个类。

        4
  •  3
  •   P.K    15 年前

    正如这里所有人提到的…

    • 锁是一个逻辑概念
    • 锁定只锁定大括号内代码块中的内容。

    但为了给你一个简短的见解:

    锁只是用来代替 Monitor.Enter Monitor.Exit . 就是那个,带锁的 监视器退出 放置在finally块中。

    所以,你是什么 事实上 锁定(在代码中)是锁定对象。所以,如果您在代码中的任何地方使用这个locker对象进行锁定,那么该代码块将被锁定。

    我猜这就是你锁的工作原理:(古鲁,如果我错了,请纠正我)

    if(locker.SyncBlockIndex <0)>                                                       
    {                                                                                
    //obtain an index to free synch cache block                                      
    //assign the index obtained in previous step to obj.SyncBlockIndex               
    }                                                                                
    syncblock = syncblockCache[locker.SyncBlockIndex]                                   
    if(!syncblock is owned by the calling thread)                                    
    {                                                                                
    //susped the calling thread                                                      
    }            
    

    看看这个链接是否能帮助你理解锁(我以前写过这个帖子)

    http://dotenetscribbles.blogspot.com/2008/10/calling-monitorenter-recursively.html

        5
  •  2
  •   Community Michael Schmitz    7 年前

    锁只是一种象征。只要某个线程持有一个特定的锁,就不允许其他线程获取该锁,从而阻止运行使用相关锁进行同步的代码。

    您可能还需要检查此问题的答案: Does lock(){} lock a resource, or does it lock a piece of code?

        6
  •  1
  •   Dewfy    15 年前

    锁不与某个对象相关-它只与一段代码相关。因此,如果您有两个不同的函数可用于全局套接字,则必须同时控制这两个函数,例如,它必须是同一个“locker”对象,因此要使这两段代码都可见。

        7
  •  1
  •   Sean    15 年前

    简短回答:否

    锁定是一个逻辑概念,而不是一个物理概念,在这个概念中,语言/CPU推断锁的作用域并限制对作用域内所有项的访问。强制使用锁是您的工作,因此如果您必须获得锁x才能使用资源y,那么您必须确保始终这样做。