代码之家  ›  专栏  ›  技术社区  ›  JoeCool

在读取全局字符串之前锁定?

  •  1
  • JoeCool  · 技术社区  · 16 年前

    可能的 后台工作程序可以读取字符串,因为它也是由主类对象写入的,尽管可能性不大。但是这两个操作(后台工作程序读取和主类写入)对于字符串文本来说不是原子的吗?

    -罗伯特

    编辑:

    7 回复  |  直到 16 年前
        1
  •  8
  •   Community Mohan Dere    9 年前

    NET中的字符串是不可变的;他们不能改变。发生的情况是,引用将指向一个完全不同的字符串,但字符串本身不会被更改。

    documentation

    这种类型是线程安全的。

    Martinho Fernandes 在下面的注释中:线程安全对象 自动意味着你用它们做的每件事都是线程安全的。他甚至写了一封信 blog post

        2
  •  3
  •   Robert Venables    16 年前

    如果您不使用锁,最坏的情况是您的后台工作人员从主类和线程的角度读取字符串的过期副本。 在处理字符串时,您永远不会(在任何情况下)遇到“在别处使用的对象”异常 (摘自问题)。

    正如在另一个答案中正确指出的那样,字符串是不可变的,在创建后不能更改。对现有字符串的任何更改都将透明地导致在堆的内存中创建一个新字符串,而不会对以前的字符串对象产生任何影响。

    使用锁(以可能可测量的性能影响为代价)将确保您的后台工作人员读取字符串的最新副本。

        3
  •  2
  •   Brian Gideon    16 年前

    是的,读取和写入将是原子到字符串变量。这是因为只有变量引用发生过更改。字符串是不可变的,因此任何修改字符串内容的操作也将创建字符串的新实例。它是通过变量交换的对新实例的引用。但是,这不是主要问题。

    一句话……如果另一个线程修改字符串变量的可能性微乎其微,那么您将需要从工作线程同步对该变量的访问,很可能还需要从主线程同步对该变量的访问。

    编辑: 因为过时与您无关,所以您可能不需要使用锁就可以了。但是,假设您在工作线程启动之前已将字符串变量初始化为某个值。

        4
  •  1
  •   Stan R.    16 年前

        5
  •  1
  •   Community Mohan Dere    9 年前

    有几个字符串A B&C如果后台工作人员正在处理(比如)A和B的v3和C的v2,这有关系吗?如果是这样,那么您需要在整个集合的更新周围设置一个锁。

    第二个微妙的问题是,C#可能选择寄存器中的缓存值,或者对代码进行逆时针重新排序,因此线程看不到相同的“现实”视图。看见 this discussion question .

    我的建议是,使用同步编写明显正确的代码。在这种情况下,性能影响肯定是微不足道的。这样,代码维护人员甚至不必担心。如果基准测试显示这是一个性能问题,那么在研究编写线程安全的聪明代码时,一定要非常非常小心。

        6
  •  0
  •   Adriaan Stander    16 年前

    是的,我建议使用锁定,如果这是一个像只读取这样的小任务,那么它应该相当简单。请注意死锁,其中一个线程锁定了一个字符串,正在等待另一个线程持有另一个锁。

        7
  •  0
  •   Dario    16 年前

    您不需要锁,因为只有当两个线程试图同时分配一个值时,才会发生这种竞争。因为.NET字符串是不可变的,所以您得到的结果永远不会被破坏——在最坏的情况下,它已经过时了。

    推荐文章