首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >` `Synclock syncroot`和` `SyncLock Me`有什么区别?

` `Synclock syncroot`和` `SyncLock Me`有什么区别?
EN

Stack Overflow用户
提问于 2010-05-18 23:10:19
回答 3查看 2.4K关注 0票数 5

vb.Net多线程问题:

它们之间的区别是什么

代码语言:javascript
复制
SyncLock syncRoot  
  ''# Do Stuff  
End SyncLock

-和-

代码语言:javascript
复制
SyncLock Me  
  ''# Do Stuff  
End SyncLock
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-05-18 23:13:04

发生在SyncLock块中的所有代码都与发生在同一对象上的SyncLock块中的所有其他代码同步。显然,MesyncRoot不同(我假设是Me.SyncRoot,如果您的MeICollection的话)。

发生在一个对象上的SyncLock块中的代码不会与另一个对象上的SyncLock块中的代码同步。

假设你有这样的代码:

代码语言:javascript
复制
' happening on thread 1 '
SyncLock myColl.SyncRoot
    myColl.Add(myObject)
End SyncLock

' happening on thread 2 '
SyncLock myColl.SyncRoot
    myColl.Remove(myObject)
End SyncLock

上面的情况很好:AddRemove调用是同步的,这意味着它们不会同时发生(首先调用的那个将执行,而第二个直到第一个调用完成后才会执行)。

但是假设你有这样的结果:

代码语言:javascript
复制
' happening on thread 1 '
SyncLock myColl.SyncRoot
    myColl.Add(myObject)
End SyncLock

' happening on thread 2 '
SyncLock myColl ' NOTE: SyncLock on a different object '
    myColl.Remove(myObject)
End SyncLock

上面的AddRemove调用是,而不是以任何方式、形状或形式同步的。因此,在上面的代码中没有线程安全性。

那么,SyncRoot为什么会存在呢?很简单,因为在必要的最小规模上进行同步是有意义的;即,不需要同步实际上不需要同步的代码。

考虑这个例子:

代码语言:javascript
复制
' happening on thread 1 '
SyncLock myColl
    myColl.Add(myObject)
End SyncLock

' happening on thread 2 '
SyncLock myColl
    ' Why you would have code like this, I do not know; '
    ' this is just for illustration. '
    myColl.Name = myColl.Name.Replace("Joe", "Bill")
End SyncLock

' happening on thread 3 '
SyncLock myColl
    myColl.Name = myColl.Name.Replace("Bill", "Joe")
End SyncLock

在上面的代码中,同步的次数超过了必要的Add调用实际上与myColl对象的重命名无关;因此代码不需要同步。

这就是SyncRoot属性背后的思想:它为您提供一个对象,其整个目的是提供一个公共对象,通过该对象可以同步对集合的修改/集合的枚举。以其他方式涉及集合的代码--但不需要与修改或读取集合内容的代码同步--应该在适当的情况下在不同的对象上进行同步。

票数 5
EN

Stack Overflow用户

发布于 2010-05-18 23:22:54

如果是Object.ReferenceEquals(syncRoot, Me) = True,那就没什么不同了。否则,将使用不同的对象获取锁。

如果您对syncRoot的使用等同于ICollection.SyncRoot,那么将使用集合内部用于其自身锁定的同一对象来获取锁。这使您可以同步对枚举数的访问。例如:

代码语言:javascript
复制
SyncLock collection.SyncRoot
  For Each item As Object in collection
  Next
End SyncLock

按照惯例,.NET开发人员避免使用Me作为锁对象。如果Me引用对类库的公共API可见的对象,则尤其如此。我们之所以避免这样做,是因为其他代码可能会使用相同的对象来获取锁,其原因与您试图在代码中实现的语义行为相冲突。这种冲突可能会导致瓶颈甚至死锁。

应该注意的是,SyncLock并不同步对锁对象本身的访问,而是同步由SyncLock构造包装的代码。换句话说,由使用相同对象的SyncLock保护的代码被有效地序列化。

票数 3
EN

Stack Overflow用户

发布于 2010-05-18 23:12:36

您正在锁定不同的对象。

如果你的代码的其他部分(或内部代码)在SyncRoot上同步,那么你在Me上同步就打破了一些东西(即引入了线程错误)。

你绝对应该在SyncRoot上同步--这就是它存在的原因。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2858540

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档