1

我有以下 vb.net 代码,我不确定这里是否存在竞争条件。

在我的测试中,我没有看到比赛条件的证据。

Public Class Worker
    Private _List As New List(Of clsTag)
    ' assume that we added tag objects to list defined above ....
    Public Sub Main()
        Dim tagCol As IEnumerable = _List 
        Parallel.ForEach(tagCol.Cast(Of Object)(), Sub(TagObj As clsTag)
            TagObj.CheckLogicValue()
        End Sub)
    End Sub
End Class

Public Class clsTag 
    Public Sub CheckLogicValue()
        ...
        glbObject.CalcSomething(Me)
        ...
    End Sub
End Class

Public Class SharedObject
    Public Function CalcSomething(ByRef objTag As clsTag) As Decimal
        ' Do some calculation based on objTag and also modify objTag status here!
    End Function
End Class

whereglbObject是一个全局对象,一个SharedObject类的实例,函数CalcSomething获取TagObj ByRef并修改这个对象。安全吗?

关于做什么CalcSomething

  • 它遍历所有标签的列表(即 a _List)并从中读取(不进行任何修改)。
  • 根据在列表中找到的内容,正在计算某个表达式,该表达式既不会更改标记对象,也不会更改列表

根据计算结果(这也是函数返回的结果)tagObject,传递的字段ByRef正在更新,所以它是这样的:

Public Class SharedObject
     Public Function CalcSomething(ByRef objTag As clsTag) As Decimal
         ' Do some calculation based on objTag and also modify objTag status here!
         if (...) then
             objTag.ItemBroken = False
         EndIf
     End Function
End Class
4

1 回答 1

0
  1. 如果中的代码CalcSomething修改(甚至使用)某些状态变量,而不是传递的参数中包含的内容,那么您确实有一个明确的竞争条件。
  2. 即使您不访问参数以外的任何内容,如果您正在更改它,如果同一对象在集合中使用两次,例如,仍然可能获得竞争条件,例如

    Dim _tag = New clsTag With {...}
    _List.Add(_tag);
    _List.Add(_tag);
    

请注意,除非我们确切知道代码在做什么,否则不可能有明确的答案。
如果仅读取全局状态,并且您绝对确定该状态在方法执行期间不会更改,那么您应该免受全局值竞争条件的影响。
此外,如果.ItemBroken(或设置的任何其他字段/属性)未在计算本身中使用,但仅作为某些(可重复)检查的结果设置,您可以合理地确定您不会参加比赛健康)状况。

另一方面,Paralel.For它不会神奇地加快您的处理速度,并且会使代码更难理解。你确定一个简单的顺序Foreach不会一样快,同时更容易理解和调试吗?

For Each TagObj As clsTag In tagCol
    TagObj.CheckLogicValue()
Next
于 2013-11-11T16:26:03.310 回答