草庐IT

c# - 关于锁的一些令人困惑的事情

coder 2024-05-23 原文

我知道如何在我的应用程序中使用锁,但仍然有几件事我不太了解锁定(顺便说一句 - 我知道 lock 语句只是使用 Monitor 类类型的速记符号)。

来自 http://msdn.microsoft.com/en-us/library/ms173179.aspx :

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

     public void Function()
     {

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

The argument provided to the lock keyword must be an object based on a reference type, and is used to define the scope of the lock. In the example above, the lock scope is limited to this function because no references to the object lockThis exist outside the function. If such a reference did exist, lock scope would extend to that object.



a) 不明白 lockThis 对象是如何定义锁的作用域的。锁的范围是之间的所有代码锁(锁这个){ 和相邻 } ,那么“锁定范围将扩展到该对象”究竟是什么意思?

b) 锁定对象锁定这个术语是什么意思?简单地说,我们使用对 lockThis 的引用来锁定代码区域?因此,该术语并不表示我们锁定了 lockThis 对象?

谢谢

回复大卫莫顿:

如果我的回答有点冗长,我深表歉意,但我想不出任何其他方式来表达我的问题并且仍然有些连贯:

  1. The scope of the lock, in this situation, is the individual instance of the class itself. This is opposed to crossing all instance of the specific class. You could have your lock cross all instances TestThreading by making lockThis static. That's what's meant by the "scope" of the lock: whether it's applicable to a single instance, or applicable to every instance of a particular type.

Other objects could still access lockThis from another thread, but they wouldn't be able to process code that is surrounded by a lock on that object.



如果我们调用被锁包围的代码(位于 TestThreading.Function 内) C ,那么由于 TestThreading.Function 不是静态的,每个 TestThreading 实例都有自己的副本 C .但是如果 TestThreading.Function 是静态的,那么所有 TestThreading 实例将共享 的相同副本。 C .打个比方,如果 C 是一个房间,如果 TestThreading.Function 不是静态的,那么每个 TestThreading 实例都会有自己的 C室 ,但如果函数是静态的,那么所有 TestThreading 实例将共享相同的 C室 .

按照这个类比,我将 lockThis 解释为 的 key 。 C室 .如果 lockThis 是静态的并且 TestThreading.Function 不是静态的,那么所有的 TestThreading 实例将使用相同的键来输入它们自己的 C房 .
  • 因此,我认为 lockThis 是否为静态没有任何意义,因为在任何一种情况下,每个 TestThreading 实例都将使用 lockThis 进入自己的房间 C(假设 TestThreading.Function 不是 static )。因此,按照该逻辑,锁的范围不应该始终是类的单个实例(假设 TestThreading.Function 不是 static )?
  • 同样,我认为 lockThis 是私有(private)的还是公共(public)的没有任何意义,因为 TestThreading 实例将再次使用 lockThis 进入自己的 C室 (假设 TestThreading.Function 不是静态的)


  • 对大卫·莫顿的第二次回复

    In response to your response: There is a significance. If TestThreading.Function is static, then lockThis has to be static, otherwise, TestThreading.Function cannot access lockThis at all.



    我不确定您所说的 TestThreading.Function 无法访问 lockThis 是什么意思?!再次假设我们调用由锁包围的代码(位于 TestThreading.Function 内) C .
    如果 TestThreading.Function 是静态的,因此只有一个房间,但是 lockThis 是非静态的,如果我们有以下定义:
     public class TestThreading
     {
        private System.Object lockThis = new System.Object();
    
        public static  void Function()
        {
    
            lock (new TestThreading().lockThis)
            {
               // Access thread-sensitive resources.
            }
        }
     }
    

    ,然后每当某个线程访问 C室 ,它将使用新 key 。因此,如果 100 个线程访问 C室 ,那么同一个房间会用 100 个不同的 key 打开?!所以代码确实有效,只是没有多大意义,因为线程之间根本没有同步?!

    The scope of the lock, in this situation, is the individual instance of the class itself. This is opposed to crossing all instance of the specific class. You could have your lock cross all instances TestThreading by making lockThis static.



    我对锁的作用域这个术语感到困惑,因为我将它解释为:如果 lockThis 是静态的,那么所有 TestThread 实例将共享同一个房间(又名锁),即使 TestThread.Function 不是静态的。假设我现在理解正确,那么术语锁是指用于打开门的 key (因此锁不是指房间?!)?

    因此,如果我们假设 lockThis 是静态的,而 TestThread.Function 不是静态的,那么 key/lock 的范围是所有 TestThread 实例,这意味着所有 TestThread 实例共享相同的 key ,因此当一个 TestThread 实例打开门时使用这把 key 进入它的房间,在第一个实例释放那把 key 之前,其他实例将无法打开他们房间的门?

    对大卫·莫顿的第三次回复

    No, if Function is static, then all TestThread instances would share the same room, if lockThis is static, then all TestThread instances would share the same key.



    您是否同意在 lock 的句子范围中使用的单词 lock 至少在某种程度上指的是 key(key 是 lockThis 实例)?

    The room is the code that is executed within the lock, not the lockThis object itself, that's simply the key.



    【防御模式开启】我上次回复就是这么说的。 ;) [防御模式关闭]

    最佳答案

  • 在这种情况下,锁的范围是类本身的单个实例。这与跨越特定类的所有实例相反。您可以通过将 lockThis 设为静态来让您的锁跨越所有 TestThreading 实例。这就是锁的“范围”的含义:它是适用于单个实例,还是适用于特定类型的每个实例。
  • “锁定对象 thisObject”只是意味着使用 thisObject 作为确定我们是否处于锁定状态的对象。该术语并不表示我们“锁定”了 lockThis 对象。我认为你的估计在这里是正确的。其他对象仍然可以从另一个线程访问 lockThis,但它们将无法处理被该对象上的锁包围的代码。

  • 由于我们正在相互回复,这里有更多信息:

    让我们以您上面概述的“房间和 key ”类比,并将其扩展到每一种可能性。我们有几种不同的情况:
  • 静态函数,静态锁对象——这类似于有一个房间,只有一把 key 。
  • 实例函数,静态锁对象 - 这就像有几个房间共享相同的 key ......例如,就像一个万能 key 。
  • 实例函数,实例锁对象 - 这就像有几个房间,每个房间都有自己的 key ......就像宿舍或酒店。
  • 静态函数,实例锁定对象 - 不可能。您无法从静态上下文访问实例字段。

  • 希望上述场景概述了这些将如何协同工作。

    回复第二个回复

    I’m not sure what you mean by TestThreading.Function not being able to access lockThis?!



    它无法访问有用的 lockThis。锁定完成后被丢弃的实例上的静态方法锁定是无用的。在您设置的场景中,每次靠近门时,锁都会“赠送”一把新 key ,并说“好吧,我接受刚刚给您的 key ……您可以进来”。在这种情况下,它过于松散地保护“房间”,让每个人都可以随时访问。换句话说,在第二个示例中甚至没有理由使用 lock 语句。这就像房间里有数量不断增加的门,只用过一次,上面贴着 key 。无数人可以随时进入。您的代码和以下代码之间没有区别,真的(有,但这是为了让您有希望获得这个概念:
    public class TestThreading
    {
        private object lockThis = new object();
    
        public static void Function() 
        {
            lockThis = new object();
            lock (lockThis)
            {
                // access something   
            }
        }
    }
    

    我在上面那个例子中所做的基本上是在我在门上使用锁之前扔掉并重新 key 。那没用。你是对的,不会有任何线程同步,从这个意义上说,我会说代码根本不起作用,因为锁的全部意义在于同步线程。

    if the lockThis was static, then all TestThread instances would share the same room (aka lock), even though TestThread.Function isn’t static. Assuming I understand it correctly now, then the term lock is referring to the key (thus lock doesn’t refer to the room?! ) used for opening the doors?



    不,如果 Function 是静态的,那么所有 TestThread 实例将共享同一个房间,如果 lockThis 是静态的,那么所有 TestThread 实例将共享相同的 key 。
    lock (key)
    {
       // room
    }
    

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

    As such, if we assume that lockThis is static and TestThread.Function is not static, then the scope of the key/lock is all TestThread instances, which means that all TestThread instances share the same key and thus when one TestThread instance opens the door to its room using this key, the other instances won’t be able to open the doors to their rooms until first instance releases that key?



    是的。

    关于c# - 关于锁的一些令人困惑的事情,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2358614/

    有关c# - 关于锁的一些令人困惑的事情的更多相关文章

    1. ruby-on-rails - 带 Spring 锁的 Rails 4 控制台 - 2

      我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.

    2. c# - 如何在 ruby​​ 中调用 C# dll? - 2

      如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

    3. C# 到 Ruby sha1 base64 编码 - 2

      我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

    4. ruby-on-rails - 如何生成传递一些自定义参数的 `link_to` URL? - 2

      我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些

    5. 基于C#实现简易绘图工具【100010177】 - 2

      C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

    6. ruby - 找一些句子 - 2

      我想找到在某些文本中找到一些(让它是两个)句子的好方法。什么会更好-使用正则表达式或拆分方法?你的想法?应JeremyStein的要求-有一些例子示例:输入:ThefirstthingtodoistocreatetheCommentmodel.We’llcreatethisinthenormalway,butwithonesmalldifference.IfwewerejustcreatingcommentsforanArticlewe’dhaveanintegerfieldcalledarticle_idinthemodeltostoretheforeignkey,butinthis

    7. ruby-on-rails - 关于 Ruby 的一般问题 - 2

      我在我的rails应用程序中安装了来自github.com的acts_as_versioned插件,但有一段代码我不完全理解,我希望有人能帮我解决这个问题class_eval我知道block内的方法(或任何它是什么)被定义为类内的实例方法,但我在插件的任何地方都找不到定义为常量的CLASS_METHODS,而且我也不确定是什么here,并且有问题的代码从lib/acts_as_versioned.rb的第199行开始。如果有人愿意告诉我这里的内幕,我将不胜感激。谢谢-C 最佳答案 这是一个异端。http://en.wikipedia

    8. ruby block 并从 block 中返回一些东西 - 2

      我正在使用ruby​​1.8.7。p=lambda{return10;}deflab(block)puts'before'putsblock.callputs'after'endlabp以上代码输出为before10after我将相同的代码重构到这里deflab(&block)puts'before'putsblock.callputs'after'endlab{return10;}现在我收到LocalJumpError:意外返回。对我来说,这两个代码都在做同样的事情。是的,在第一种情况下我传递了一个过程,在第二种情况下我传递了一个block。但是&block将该block转换为pro

    9. ruby - 我怎样才能更好地了解/了解更多关于 Ruby 的知识? - 2

      按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭9年前。我最近开始学习Ruby,这是我的第一门编程语言。我对语法感到满意,并且我已经完成了许多只教授相同基础知识的教程。我已经写了一些小程序(包括我自己的数组排序方法,在有人告诉我谷歌“冒泡排序”之前我认为它非常聪明),但我觉得我需要尝试更大更难的东西来理解更多关于Ruby.关于如何执行此操作的任何想法?

    10. ruby - 关于 Ruby 中 Dir[] 和 File.join() 的混淆 - 2

      我在Ruby中遇到了一个关于Dir[]和File.join()的简单程序,blobs_dir='/path/to/dir'Dir[File.join(blobs_dir,"**","*")].eachdo|file|FileUtils.rm_rf(file)ifFile.symlink?(file)我有两个困惑:首先,File.join(@blobs_dir,"**","*")中的第二个和第三个参数是什么意思?其次,Dir[]在Ruby中有什么用?我只知道它等价于Dir.glob(),但是,我对Dir.glob()确实不是很清楚。 最佳答案

    随机推荐