ArrayList in Thread question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • fniles

    ArrayList in Thread question

    I am using VB.NET 2003 and a socket control to receive and sending data to
    clients.
    As I receive data in 1 thread, I put it into an arraylist, and then I remove
    the data from arraylist and send it to the client.
    Before adding data to the arraylist, I check if the depth of the arraylist
    is longer than iMaxQueueDepth, and if it is, I clear the arraylist.
    Is it possible that while I am clearing the arraylist, the ThreadMain at the
    same time also trying to remove the data in the arraylist ?
    In other words, in the following codes, in the Sub NewQuote doing
    QuotesSync.Add( Message) at the same time ThreadMain doing
    sPacket = QuotesSync(0)
    QuotesSync.Remo veAt(0)
    ?

    Thank you.

    Public Class ListenerClass
    ClientSession = New SessionClass
    ' Create a new worker thread to handle the client session
    ClientThread = New Threading.Threa d(AddressOf ClientSession.T hreadMain)
    end class

    Public Class frmQuoteServer
    Public Function RegisterClient( ByRef Session As SessionClass, ByRef Thread
    As Threading.Threa d) As Boolean
    ReDim Preserve Client(LastClie nt)
    client(LastClie nt).Session = Session
    Client(LastClie nt).Thread = Thread
    end Function

    Sub ProcessEachMess age
    'This sub is called by another thread that receives quotes
    For lIndex = 0 To LastClient - 1
    'assigning the quote to the client session
    Client(lIndex). Session.NewQuot e(sStr)
    next
    end sub
    end Class

    Public Class SessionClass
    Public Server As frmQuoteServer
    Private Quotes As New ArrayList
    Private QuotesSync As ArrayList = ArrayList.Synch ronized(Quotes)

    Sub NewQuote(ByVal Message As String)
    'this sub is called a receiving data thread receives data
    If QuotesSync.Coun t iMaxQueueDepth Then QuotesSync.Clea r() 'clear the
    queue if it is longer than iMaxQueueDepth
    QuotesSync.Add( Message)
    end Sub

    Public Sub ThreadMain()
    If Server.Register Client(Me, Thread.CurrentT hread()) = False Then
    :
    Exit Sub
    End If

    'this client thread is looping all the time until it is terminated
    Do While Not Terminated
    sPacket = ""
    While QuotesSync.Coun t 0 And Not (Terminated)
    sPacket = QuotesSync(0)
    nResult = Socket.Write(sP acket)
    QuotesSync.Remo veAt(0)
    End While
    Thread.Sleep(1)
    Loop
    end Sub
    end class


  • fniles

    #2
    Re: ArrayList in Thread question

    Thank you for your reply.
    Do I understand it correctly that when I synchronized an arraylist, it will
    be thread safe and it won't throw an exception even when other threads
    modify the arraylist, but when I synchronized a collection it will still
    throw an exception ?



    "Kerry Moorman" <KerryMoorman@d iscussions.micr osoft.comwrote in message
    news:0C8B20DB-8976-450B-AC40-FE1178B3C8DA@mi crosoft.com...
    fniles,
    >
    Have you noticed that the Help system always has information about a
    class's
    thread safety as some of the very first information about the class?
    >
    Here is the help information about thread safety for an arraylist:
    >
    Thread Safety
    Public static (Shared in Visual Basic) members of this type are safe for
    multithreaded operations. Instance members are not guaranteed to be
    thread-safe.
    >
    An ArrayList can support multiple readers concurrently, as long as the
    collection is not modified. To guarantee the thread safety of the
    ArrayList,
    all operations must be done through the wrapper returned by the
    Synchronized
    method.
    >
    Enumerating through a collection is intrinsically not a thread-safe
    procedure. Even when a collection is synchronized, other threads could
    still
    modify the collection, which causes the enumerator to throw an exception.
    To
    guarantee thread safety during enumeration, you can either lock the
    collection during the entire enumeration or catch the exceptions resulting
    from changes made by other threads.
    >
    Kerry Moorman
    >
    >
    "fniles" wrote:
    >
    >I am using VB.NET 2003 and a socket control to receive and sending data
    >to
    >clients.
    >As I receive data in 1 thread, I put it into an arraylist, and then I
    >remove
    >the data from arraylist and send it to the client.
    >Before adding data to the arraylist, I check if the depth of the
    >arraylist
    >is longer than iMaxQueueDepth, and if it is, I clear the arraylist.
    >Is it possible that while I am clearing the arraylist, the ThreadMain at
    >the
    >same time also trying to remove the data in the arraylist ?
    >In other words, in the following codes, in the Sub NewQuote doing
    >QuotesSync.Add (Message) at the same time ThreadMain doing
    > sPacket = QuotesSync(0)
    > QuotesSync.Remo veAt(0)
    >?
    >>
    >Thank you.
    >>
    >Public Class ListenerClass
    > ClientSession = New SessionClass
    > ' Create a new worker thread to handle the client session
    > ClientThread = New Threading.Threa d(AddressOf ClientSession.T hreadMain)
    >end class
    >>
    >Public Class frmQuoteServer
    >Public Function RegisterClient( ByRef Session As SessionClass, ByRef
    >Thread
    >As Threading.Threa d) As Boolean
    > ReDim Preserve Client(LastClie nt)
    > client(LastClie nt).Session = Session
    > Client(LastClie nt).Thread = Thread
    >end Function
    >>
    >Sub ProcessEachMess age
    >'This sub is called by another thread that receives quotes
    > For lIndex = 0 To LastClient - 1
    > 'assigning the quote to the client session
    > Client(lIndex). Session.NewQuot e(sStr)
    > next
    >end sub
    >end Class
    >>
    >Public Class SessionClass
    > Public Server As frmQuoteServer
    > Private Quotes As New ArrayList
    > Private QuotesSync As ArrayList = ArrayList.Synch ronized(Quotes)
    >>
    >Sub NewQuote(ByVal Message As String)
    >'this sub is called a receiving data thread receives data
    > If QuotesSync.Coun t iMaxQueueDepth Then QuotesSync.Clea r() 'clear
    >the
    >queue if it is longer than iMaxQueueDepth
    > QuotesSync.Add( Message)
    >end Sub
    >>
    >Public Sub ThreadMain()
    > If Server.Register Client(Me, Thread.CurrentT hread()) = False Then
    > :
    > Exit Sub
    > End If
    >>
    >'this client thread is looping all the time until it is terminated
    > Do While Not Terminated
    > sPacket = ""
    > While QuotesSync.Coun t 0 And Not (Terminated)
    > sPacket = QuotesSync(0)
    > nResult = Socket.Write(sP acket)
    > QuotesSync.Remo veAt(0)
    > End While
    > Thread.Sleep(1)
    > Loop
    >end Sub
    >end class
    >>
    >>
    >>

    Comment

    • =?Utf-8?B?S2VycnkgTW9vcm1hbg==?=

      #3
      Re: ArrayList in Thread question

      fniles,

      Here the documentation is using the term "collection " to refer to all
      collections, including arraylist collections.

      Kerry Moorman


      "fniles" wrote:
      Thank you for your reply.
      Do I understand it correctly that when I synchronized an arraylist, it will
      be thread safe and it won't throw an exception even when other threads
      modify the arraylist, but when I synchronized a collection it will still
      throw an exception ?
      >
      >
      >
      "Kerry Moorman" <KerryMoorman@d iscussions.micr osoft.comwrote in message
      news:0C8B20DB-8976-450B-AC40-FE1178B3C8DA@mi crosoft.com...
      fniles,

      Have you noticed that the Help system always has information about a
      class's
      thread safety as some of the very first information about the class?

      Here is the help information about thread safety for an arraylist:

      Thread Safety
      Public static (Shared in Visual Basic) members of this type are safe for
      multithreaded operations. Instance members are not guaranteed to be
      thread-safe.

      An ArrayList can support multiple readers concurrently, as long as the
      collection is not modified. To guarantee the thread safety of the
      ArrayList,
      all operations must be done through the wrapper returned by the
      Synchronized
      method.

      Enumerating through a collection is intrinsically not a thread-safe
      procedure. Even when a collection is synchronized, other threads could
      still
      modify the collection, which causes the enumerator to throw an exception.
      To
      guarantee thread safety during enumeration, you can either lock the
      collection during the entire enumeration or catch the exceptions resulting
      from changes made by other threads.

      Kerry Moorman


      "fniles" wrote:
      I am using VB.NET 2003 and a socket control to receive and sending data
      to
      clients.
      As I receive data in 1 thread, I put it into an arraylist, and then I
      remove
      the data from arraylist and send it to the client.
      Before adding data to the arraylist, I check if the depth of the
      arraylist
      is longer than iMaxQueueDepth, and if it is, I clear the arraylist.
      Is it possible that while I am clearing the arraylist, the ThreadMain at
      the
      same time also trying to remove the data in the arraylist ?
      In other words, in the following codes, in the Sub NewQuote doing
      QuotesSync.Add( Message) at the same time ThreadMain doing
      sPacket = QuotesSync(0)
      QuotesSync.Remo veAt(0)
      ?
      >
      Thank you.
      >
      Public Class ListenerClass
      ClientSession = New SessionClass
      ' Create a new worker thread to handle the client session
      ClientThread = New Threading.Threa d(AddressOf ClientSession.T hreadMain)
      end class
      >
      Public Class frmQuoteServer
      Public Function RegisterClient( ByRef Session As SessionClass, ByRef
      Thread
      As Threading.Threa d) As Boolean
      ReDim Preserve Client(LastClie nt)
      client(LastClie nt).Session = Session
      Client(LastClie nt).Thread = Thread
      end Function
      >
      Sub ProcessEachMess age
      'This sub is called by another thread that receives quotes
      For lIndex = 0 To LastClient - 1
      'assigning the quote to the client session
      Client(lIndex). Session.NewQuot e(sStr)
      next
      end sub
      end Class
      >
      Public Class SessionClass
      Public Server As frmQuoteServer
      Private Quotes As New ArrayList
      Private QuotesSync As ArrayList = ArrayList.Synch ronized(Quotes)
      >
      Sub NewQuote(ByVal Message As String)
      'this sub is called a receiving data thread receives data
      If QuotesSync.Coun t iMaxQueueDepth Then QuotesSync.Clea r() 'clear
      the
      queue if it is longer than iMaxQueueDepth
      QuotesSync.Add( Message)
      end Sub
      >
      Public Sub ThreadMain()
      If Server.Register Client(Me, Thread.CurrentT hread()) = False Then
      :
      Exit Sub
      End If
      >
      'this client thread is looping all the time until it is terminated
      Do While Not Terminated
      sPacket = ""
      While QuotesSync.Coun t 0 And Not (Terminated)
      sPacket = QuotesSync(0)
      nResult = Socket.Write(sP acket)
      QuotesSync.Remo veAt(0)
      End While
      Thread.Sleep(1)
      Loop
      end Sub
      end class
      >
      >
      >
      >
      >
      >

      Comment

      • fniles

        #4
        Re: ArrayList in Thread question

        THanks.
        To guarantee thread safety during enumeration, you can either lock the
        collection during the entire enumeration or catch the exceptions
        resulting
        from changes made by other threads.
        If I lock the arraylist, and another thread try to modify it, what will
        happen there ?

        "Kerry Moorman" <KerryMoorman@d iscussions.micr osoft.comwrote in message
        news:AE47BC8A-9970-46A2-A8A6-9CE6FD2D2C74@mi crosoft.com...
        fniles,
        >
        Here the documentation is using the term "collection " to refer to all
        collections, including arraylist collections.
        >
        Kerry Moorman
        >
        >
        "fniles" wrote:
        >
        >Thank you for your reply.
        >Do I understand it correctly that when I synchronized an arraylist, it
        >will
        >be thread safe and it won't throw an exception even when other threads
        >modify the arraylist, but when I synchronized a collection it will still
        >throw an exception ?
        >>
        >>
        >>
        >"Kerry Moorman" <KerryMoorman@d iscussions.micr osoft.comwrote in message
        >news:0C8B20D B-8976-450B-AC40-FE1178B3C8DA@mi crosoft.com...
        fniles,
        >
        Have you noticed that the Help system always has information about a
        class's
        thread safety as some of the very first information about the class?
        >
        Here is the help information about thread safety for an arraylist:
        >
        Thread Safety
        Public static (Shared in Visual Basic) members of this type are safe
        for
        multithreaded operations. Instance members are not guaranteed to be
        thread-safe.
        >
        An ArrayList can support multiple readers concurrently, as long as the
        collection is not modified. To guarantee the thread safety of the
        ArrayList,
        all operations must be done through the wrapper returned by the
        Synchronized
        method.
        >
        Enumerating through a collection is intrinsically not a thread-safe
        procedure. Even when a collection is synchronized, other threads could
        still
        modify the collection, which causes the enumerator to throw an
        exception.
        To
        guarantee thread safety during enumeration, you can either lock the
        collection during the entire enumeration or catch the exceptions
        resulting
        from changes made by other threads.
        >
        Kerry Moorman
        >
        >
        "fniles" wrote:
        >
        >I am using VB.NET 2003 and a socket control to receive and sending
        >data
        >to
        >clients.
        >As I receive data in 1 thread, I put it into an arraylist, and then I
        >remove
        >the data from arraylist and send it to the client.
        >Before adding data to the arraylist, I check if the depth of the
        >arraylist
        >is longer than iMaxQueueDepth, and if it is, I clear the arraylist.
        >Is it possible that while I am clearing the arraylist, the ThreadMain
        >at
        >the
        >same time also trying to remove the data in the arraylist ?
        >In other words, in the following codes, in the Sub NewQuote doing
        >QuotesSync.Add (Message) at the same time ThreadMain doing
        > sPacket = QuotesSync(0)
        > QuotesSync.Remo veAt(0)
        >?
        >>
        >Thank you.
        >>
        >Public Class ListenerClass
        > ClientSession = New SessionClass
        > ' Create a new worker thread to handle the client session
        > ClientThread = New Threading.Threa d(AddressOf
        >ClientSession. ThreadMain)
        >end class
        >>
        >Public Class frmQuoteServer
        >Public Function RegisterClient( ByRef Session As SessionClass, ByRef
        >Thread
        >As Threading.Threa d) As Boolean
        > ReDim Preserve Client(LastClie nt)
        > client(LastClie nt).Session = Session
        > Client(LastClie nt).Thread = Thread
        >end Function
        >>
        >Sub ProcessEachMess age
        >'This sub is called by another thread that receives quotes
        > For lIndex = 0 To LastClient - 1
        > 'assigning the quote to the client session
        > Client(lIndex). Session.NewQuot e(sStr)
        > next
        >end sub
        >end Class
        >>
        >Public Class SessionClass
        > Public Server As frmQuoteServer
        > Private Quotes As New ArrayList
        > Private QuotesSync As ArrayList = ArrayList.Synch ronized(Quotes)
        >>
        >Sub NewQuote(ByVal Message As String)
        >'this sub is called a receiving data thread receives data
        > If QuotesSync.Coun t iMaxQueueDepth Then QuotesSync.Clea r() 'clear
        >the
        >queue if it is longer than iMaxQueueDepth
        > QuotesSync.Add( Message)
        >end Sub
        >>
        >Public Sub ThreadMain()
        > If Server.Register Client(Me, Thread.CurrentT hread()) = False Then
        > :
        > Exit Sub
        > End If
        >>
        >'this client thread is looping all the time until it is terminated
        > Do While Not Terminated
        > sPacket = ""
        > While QuotesSync.Coun t 0 And Not (Terminated)
        > sPacket = QuotesSync(0)
        > nResult = Socket.Write(sP acket)
        > QuotesSync.Remo veAt(0)
        > End While
        > Thread.Sleep(1)
        > Loop
        >end Sub
        >end class
        >>
        >>
        >>
        >>
        >>
        >>

        Comment

        • Tom Shelton

          #5
          Re: ArrayList in Thread question

          On 2007-01-06, fniles <fniles@pfmail. comwrote:
          THanks.
          >To guarantee thread safety during enumeration, you can either lock the
          >collection during the entire enumeration or catch the exceptions
          >resulting
          >from changes made by other threads.
          If I lock the arraylist, and another thread try to modify it, what will
          happen there ?
          There are a lot of issues with threading and collections. You have to be very
          careful - even with a syncronized wrapper. The fact, is that lots of stuff
          can happen in a multi-threaded program in orders that you do not intend.. for
          example:

          sub somesub ' run on a thread
          arraylist.clear ()
          end sub


          function acoolfunction 'run on a different thread
          if arraylist.count 0
          return arraylist(0)
          end if
          end function

          hmmm, this is a syncronized collection, but the problem is that it is only
          syncronized between calls to it's methods - so what happens if you get this
          order of execution:

          'arraylist starts with count 10
          function acoolfunction
          if arraylist.count 0

          ---- Task switch

          sub somesub
          arraylist.clear ()

          --- Task Switch

          return arraylist(0) ' BIG FAT EXCEPTION

          See, in these kinds of operations, you really need something like an sql
          transaction - to treat multiple operations as atomic. You achieve that using
          the synclock statement (or some other locking mechanism, such as
          system.threadin g.monitor). This is refered to as a "critical section". Then
          the code would look something like:

          sub somesub ' run on a thread
          synclock arraylist.syncr oot
          arraylist.clear ()
          end synclock
          end sub

          function acoolfunction ' run on a different thread
          synclock arraylist.syncr oot ' lock the arraylist
          if arraylist.count 0
          return arraylist(0)
          endif
          end synclock
          end function

          Now those blocks of code can not be entered at the same time... This makes
          sure that the execution scenario from my example does not occur. All requests
          will be queued, until the end of the synclock block... Make sense? Also, be
          aware that the object you lock on needs to be the same for all the sync'd
          operations and it must be a reference type. You can pass in a value, type and
          you won't get a compiler error - you code just won't be thread safe. This is
          because synclock expects the sync object to be of type object - if you pass in
          say an integer value, then it will be boxed - but the object wrapper will be
          different in each block of code.

          I find most of the operations I do are like the above and involve multiple calls
          to the collection, so I very seldom use the syncronized wrapper - that just
          adds extra locking overhead for every call. So, I tend to use code similar to
          the above, which does basically the same thing except over mutlipe calls.

          Watch out for deadlocks, etc. Multi-threaded code is very hard to get right,
          so be prepared for problems :) I have done quite a bit of multi-threaded code
          over the last couple of years - and I still don't feel I'm anywhere near an
          expert at it...

          --
          Tom Shelton

          Comment

          • fniles

            #6
            Re: ArrayList in Thread question

            Thank you very much for your reply.

            I have a few more questions.
            1. In your example using the synclock statement, did you mean that you use
            arraylist and not the syncronized arraylist with the synclock ?
            2. >Also, be aware that the object you lock on needs to be the same for all
            the sync'd operations and it must be a reference type.
            In my program I did not pass in the parameter. The arraylist and its
            syncronized arraylist are in the class like the following:
            Private Quotes As New ArrayList
            Private QuotesSync As ArrayList = ArrayList.Synch ronized(Quotes)
            3. Can I simply trap the exception when it happen like the following ?
            sub somesub ' run on a thread
            try
            arraylist.clear ()
            Catch ex As Exception
            End Try
            end sub

            function acoolfunction 'run on a different thread
            if arraylist.count 0
            try
            return arraylist(0)
            Catch ex As Exception
            End Try
            end if
            end function

            4. What can I do when deadlocks happens ?



            "Tom Shelton" <tom_shelton@co mcastXXXXXXX.ne twrote in message
            news:6d6dnTf-zPkxgz3YnZ2dnUV Z_vqpnZ2d@comca st.com...
            On 2007-01-06, fniles <fniles@pfmail. comwrote:
            >THanks.
            >>To guarantee thread safety during enumeration, you can either lock
            >>the
            >>collection during the entire enumeration or catch the exceptions
            >>resulting
            >>from changes made by other threads.
            >If I lock the arraylist, and another thread try to modify it, what will
            >happen there ?
            >
            There are a lot of issues with threading and collections. You have to be
            very
            careful - even with a syncronized wrapper. The fact, is that lots of
            stuff
            can happen in a multi-threaded program in orders that you do not intend..
            for
            example:
            >
            sub somesub ' run on a thread
            arraylist.clear ()
            end sub
            >
            >
            function acoolfunction 'run on a different thread
            if arraylist.count 0return arraylist(0)
            end if
            end function
            >
            hmmm, this is a syncronized collection, but the problem is that it is only
            syncronized between calls to it's methods - so what happens if you get
            this
            order of execution:
            >
            'arraylist starts with count 10
            function acoolfunction
            if arraylist.count 0
            >
            ---- Task switch
            >
            sub somesub
            arraylist.clear ()
            >
            --- Task Switch
            >
            return arraylist(0) ' BIG FAT EXCEPTION
            >
            See, in these kinds of operations, you really need something like an sql
            transaction - to treat multiple operations as atomic. You achieve that
            using
            the synclock statement (or some other locking mechanism, such as
            system.threadin g.monitor). This is refered to as a "critical section".
            Then
            the code would look something like:
            >
            sub somesub ' run on a thread
            synclock arraylist.syncr oot
            arraylist.clear ()
            end synclock
            end sub
            >
            function acoolfunction ' run on a different thread
            synclock arraylist.syncr oot ' lock the arraylist
            if arraylist.count 0
            return arraylist(0)
            endif
            end synclock
            end function
            >
            Now those blocks of code can not be entered at the same time... This
            makes
            sure that the execution scenario from my example does not occur. All
            requests
            will be queued, until the end of the synclock block... Make sense? Also,
            be
            aware that the object you lock on needs to be the same for all the sync'd
            operations and it must be a reference type. You can pass in a value, type
            and
            you won't get a compiler error - you code just won't be thread safe. This
            is
            because synclock expects the sync object to be of type object - if you
            pass in
            say an integer value, then it will be boxed - but the object wrapper will
            be
            different in each block of code.
            >
            I find most of the operations I do are like the above and involve multiple
            calls
            to the collection, so I very seldom use the syncronized wrapper - that
            just
            adds extra locking overhead for every call. So, I tend to use code
            similar to
            the above, which does basically the same thing except over mutlipe calls.
            >
            Watch out for deadlocks, etc. Multi-threaded code is very hard to get
            right,
            so be prepared for problems :) I have done quite a bit of multi-threaded
            code
            over the last couple of years - and I still don't feel I'm anywhere near
            an
            expert at it...
            >
            --
            Tom Shelton

            Comment

            • Tom Shelton

              #7
              Re: ArrayList in Thread question

              On 2007-01-07, fniles <fniles@pfmail. comwrote:
              Thank you very much for your reply.
              >
              I have a few more questions.
              1. In your example using the synclock statement, did you mean that you use
              arraylist and not the syncronized arraylist with the synclock ?
              I generally don't use a sync'd arraylist. Simply because it is rare that I
              use atomic operations, generally I want to do stuff like in my acoolfunction -
              do a test and an operation. The sync'd arraylist won't do anything for you in
              these cases - except add the extra locking overhead. So, I generally just use
              the arraylist with it's syncroot property.
              2. >Also, be aware that the object you lock on needs to be the same for all
              the sync'd operations and it must be a reference type.
              In my program I did not pass in the parameter. The arraylist and its
              syncronized arraylist are in the class like the following:
              Private Quotes As New ArrayList
              Private QuotesSync As ArrayList = ArrayList.Synch ronized(Quotes)
              That's fine. My code was psuedo code. So, in your case:

              SyncLock Me.Quotes.SyncR oot
              ' do cool stuff with quotes
              End SyncLock

              You just need to make sure that all the methods you are syncronizing are using
              the same reference.
              3. Can I simply trap the exception when it happen like the following ?
              sub somesub ' run on a thread
              try
              arraylist.clear ()
              Catch ex As Exception
              End Try
              end sub
              >
              function acoolfunction 'run on a different thread
              if arraylist.count 0
              try
              return arraylist(0)
              Catch ex As Exception
              End Try
              end if
              end function
              >
              Sure. You could trap the exception. The point of the example was to show
              what might happen... You just need to be aware that in a multi-threaded
              application you can not be sure of your order of execution - so in some cases
              you need to introduce locking to ensure that bad things don't happen.
              4. What can I do when deadlocks happens ?
              Not a lot :) The thing to do with deadlocks is to make sure they don't
              happen. There are lots of techniques on the web for doing so. One is using a
              timed lock. There is a discussion of this technique at:



              The code is C#, but this would apply in VB.NET as well.

              There are other techniques for prevention and detection of deadlocks - but
              that is a very advanced topic. One that I myself am still exploring. Like I
              said, I'm far from an expert on this topic - even though I've done lots of it
              over the last two to three years :)

              --
              Tom Shelton

              Comment

              Working...