我应该始终锁定静态方法吗?
在以下示例中,GetList 返回静态(共享)变量的实例。为了线程安全,需要加锁。
但是如果 DoSomething 在方法之外不使用任何静态变量呢?也需要加锁吗?
编辑:我想澄清一下,在这种特殊情况下,我希望 DoSomething 始终按顺序打印 0-100 (即没有 0123745...),无论调用线程的数量如何。或者,一般来说,不同的线程不会影响彼此的变量(打印到控制台只是一个示例)。以下示例中的语言是 VB.NET。
正如帕克斯迪亚布罗所说:
在这种情况下,似乎唯一触及的是局部变量 我每个函数调用都会有一个单独的副本。 换句话说,它不需要保护。
这正是我想要解决的问题。谢谢你!
Public Class TestClass
Private Shared lock As New Object
Private Shared list As List(Of Integer)
Public Shared Function GetList() As List(Of Integer)
SyncLock lock
If list Is Nothing Then
list = New List(Of Integer)
End If
Return list
End SyncLock
End Function
Public Shared Sub DoSomething()
Dim i As Integer
For i = 0 To 100
Console.WriteLine(i.ToString)
Next
End Sub
End Class
In the following example GetList returns an instance of a static (shared) variable. That one needs locking in order to be thread-safe.
But what about DoSomething which doesn't use any static variables outside the method? Does it need locking too?
EDIT: I'd like to clarify that in this particular case I expect DoSomething to always print 0-100 in sequence (i.e. no 0123745...) regardless of number of calling threads. Or, in general, that different threads don't affect each other's variables (printing to console is only an example). The language in the following example is VB.NET.
As paxdiablo said:
In this case, it appears the only thing touched is the local variable
i which would have a separate copy for every function invocation.
In other words, it wouldn't need protecting.
That is exactly what I was trying to solve. Thank you!
Public Class TestClass
Private Shared lock As New Object
Private Shared list As List(Of Integer)
Public Shared Function GetList() As List(Of Integer)
SyncLock lock
If list Is Nothing Then
list = New List(Of Integer)
End If
Return list
End SyncLock
End Function
Public Shared Sub DoSomething()
Dim i As Integer
For i = 0 To 100
Console.WriteLine(i.ToString)
Next
End Sub
End Class
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
好吧,这主要取决于您未指定的语言,但通常,如果代码不触及另一个线程也可以触及的资源,则不必受到保护。
在这种情况下,似乎唯一触及的是局部变量
i
,它为每个函数调用都有一个单独的副本。换句话说,它不需要保护。当然,可以说控制台也是一种资源,并且可能需要保护,例如,如果您不希望行相互干扰(同步写入)或希望将整个一百行作为一个单元输出(同步整个 for 循环)。
但这并不能真正保护控制台,只是保护使用它的代码块。如果不使用此方法,其他线程仍然能够写入控制台。
最重要的是,我认为第二种方法不需要同步锁。
如果您在 VB.Net 中使用 SyncLock(现在看来就是这种情况),那么下面的这一部分是不相关的。该语言保证无论您如何离开块,锁都会被释放。我会出于歇斯底里的目的而保留它。
我会有点担心第一个方法中的同步锁放置,特别是如果返回语句是将控制权转移回调用者(并且同步锁不会在范围更改时自动解锁) 。看起来你可以在不解锁的情况下返回,这将是一场灾难。我认为以下内容更合适:
Well, that would mostly depend on the language which you haven't specified but, generally, if code doesn't touch a resource that another thread can also touch, it doesn't have to be protected.
In this case, it appears the only thing touched is the local variable
i
which would have a separate copy for every function invocation. In other words, it wouldn't need protecting.Of course, it could be argued that the console is also a resource and may need protection if, for example, you didn't want lines interfering with each other (synclock the write) or wanted the entire hundred lines output as a single unit (synclock the entire for loop).
But that won't really protect the console, just the block of code here that uses it. Other threads will still be able to write to the console by not using this method.
Bottom line, I don't think you need a synclock in the second method.
This section below is not relevant if you're using SyncLock in VB.Net (as now seems to be the case). The language guarantees that the lock is released no matter how you leave the block. I'll leave it in for hysterical purposes.
I'd be a little concerned about your synclock placement in the first method, especially if the return statement was a transfer of control back to the caller (and the synclock didn't automatically unlock on scope change). This looks like you can return without unlocking, which would be a disaster. I would think the following would be more suitable:
一般来说,没有。
您需要清楚
GetList
应用锁定的原因。正如您在第一句话中所暗示的那样,它并不是因为它返回一个静态变量。您可以删除锁定代码,并且GetList
仍然是线程安全的。但是,通过锁定,还有一个额外的保证 - 该列表只会创建一次,并且此代码的所有调用者都将收到对同一列表的引用。In general, no.
You need to be clear on the reason why
GetList
has the locking applied. It's not, as you imply in your first sentence, because it's returning a static variable. You could remove the locking code, andGetList
would still be thread safe. But, with the locking, there's an additional guarantee - that the list will only be created once, and all callers of this code will receive a reference to the same list.为什么不完全避免锁定并这样做:
Why not avoid the lock altogether and just do this: