Parallel.Foreach中可能的竞争条件

时间:2013-11-11 11:38:48

标签: .net vb.net parallel.foreach

我有以下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

其中glbObject是全局对象,SharedObject类的实例,函数CalcSomething获取TagObj ByRef并修改此对象。 安全吗?

关于CalcSomething的作用:

  • 它遍历所有标签的列表(_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

1 个答案:

答案 0 :(得分:0)

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

    Dim _tag = New clsTag With {...}
    _List.Add(_tag);
    _List.Add(_tag);
    
  3. 请注意,除非我们确切知道代码正在做什么,否则无法给出明确的答案 如果仅读取全局状态,并且您绝对确定在执行该方法期间不会更改该状态,那么您应该避免全局值竞争条件。
    此外,如果.ItemBroken(或任何其他设置的字段/属性)未在计算本身中使用,但仅作为某些(可重复)检查的结果而设置,则可以合理地确定您赢了没有竞争条件。

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

    For Each TagObj As clsTag In tagCol
        TagObj.CheckLogicValue()
    Next