collections doubt
-
Hi! I have a collection where i keep objects of a certain type.From time to time i need to enumerate the collection and access some properties of that object to know if that object is obsolete and remove it from the collection. Many threads manipulate those objects, ones for reading others for writing. My question is: to assuere thread-safety should i lock the collection or the current Object being processed? I ask this because even though the collection is locked if another thread changes the object directly the lock to the collection is useless!!! Anyone can help me with this? Another question: if i have a synchronized version of the collection, if another thread modifies the collection through a synchronized version of the collection will it afect the first thread? thx in advance Never say never
-
Hi! I have a collection where i keep objects of a certain type.From time to time i need to enumerate the collection and access some properties of that object to know if that object is obsolete and remove it from the collection. Many threads manipulate those objects, ones for reading others for writing. My question is: to assuere thread-safety should i lock the collection or the current Object being processed? I ask this because even though the collection is locked if another thread changes the object directly the lock to the collection is useless!!! Anyone can help me with this? Another question: if i have a synchronized version of the collection, if another thread modifies the collection through a synchronized version of the collection will it afect the first thread? thx in advance Never say never
If you synchronize access to the collection, the thread that gets to the collection second will block until the first thread releases its lock. As is plastered all over the .NET Framework documentation, enumerating a collection is not a thread-safe operation. From the Array class documentation:
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.
This implementation does not provide a synchronized (thread-safe) wrapper for an Array;
however, .NET Framework classes based on Array provide their own synchronized version of the
collection using the SyncRoot property.
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.RageInTheMachine9532 "...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
-
If you synchronize access to the collection, the thread that gets to the collection second will block until the first thread releases its lock. As is plastered all over the .NET Framework documentation, enumerating a collection is not a thread-safe operation. From the Array class documentation:
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.
This implementation does not provide a synchronized (thread-safe) wrapper for an Array;
however, .NET Framework classes based on Array provide their own synchronized version of the
collection using the SyncRoot property.
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.RageInTheMachine9532 "...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
Hi! But in order for the second thread to stay blocked i need to put the code in the first thread protected by a syncLock block right? Never say never
-
Hi! But in order for the second thread to stay blocked i need to put the code in the first thread protected by a syncLock block right? Never say never
All of your access to the array much use SyncLock, not just the main thread enumeration. If every access to the array goes through SyncLock, there's no threading issues. So, read up on Array.SyncLock[^]. Put some test code together and play with it! RageInTheMachine9532 "...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
-
Hi! But in order for the second thread to stay blocked i need to put the code in the first thread protected by a syncLock block right? Never say never
You need to do two things: 1) Ensure that no other thread is actively modifying the collection or any of it's members. 2) Ensure that no other thread is currently reading any collection members since collection access is not inherently threadsafe. MSDN does a generally poor job of describing thread synchronization in VB.NET. Their examples explain just enough to get you into trouble, mostly. The problem is a synckLock, aka critical section, will only protect a section of code. If you put a critical section on, for example, the collection Delete method this will ensure that only one thread can delete a collection member at any given time, but it provides no guarantees that other threads are not currently enumerating the collection, so you would still get errors. The only way you could accomplish thread safe access using a syncLock (aka critical section) with a collection is if you put the syncLock on the enumeration code, AND you ONLY modify a collection or it's members within the For ..Next loop. This has two very obnoxious side effects: Of course, only allowing write access within a For .. Each enumeration results in awkward and inefficient code. All other threads are blocked when a single thread accesses the collection for any reason. What you really want is to only lock the collection when one thread needs to modify it. So syncLock really is not suitable for this scenario. The correct way to do this is to implement locking if and only if a thread needs to modify the collection. I'll explain how to do this the old-fashioned way with mutexes and semaphores. The following procedure will ensure thread safe collection usage with minimal unneccessary locking. Execute the following steps to "write" protect a collection, i.e. when a thread intends to access the collection for modification. 1) When a thread wishes to modify the collection or it's members it must first acquire a mutex. The mutex is only available to one thread at any given time and is used to block all other threads from either read or write access to the collection. 2) After the "writer" thread acquires the mutex, it must wait until all other threads have released their semaphores which occurs when all other threads which are actively accessing the collection as "readers" have finished. 3) When all semaphores are signalled, the "writer" is ensured it is sole access to the collection and the collection or any of it's members may safely be modified because all other thre
-
You need to do two things: 1) Ensure that no other thread is actively modifying the collection or any of it's members. 2) Ensure that no other thread is currently reading any collection members since collection access is not inherently threadsafe. MSDN does a generally poor job of describing thread synchronization in VB.NET. Their examples explain just enough to get you into trouble, mostly. The problem is a synckLock, aka critical section, will only protect a section of code. If you put a critical section on, for example, the collection Delete method this will ensure that only one thread can delete a collection member at any given time, but it provides no guarantees that other threads are not currently enumerating the collection, so you would still get errors. The only way you could accomplish thread safe access using a syncLock (aka critical section) with a collection is if you put the syncLock on the enumeration code, AND you ONLY modify a collection or it's members within the For ..Next loop. This has two very obnoxious side effects: Of course, only allowing write access within a For .. Each enumeration results in awkward and inefficient code. All other threads are blocked when a single thread accesses the collection for any reason. What you really want is to only lock the collection when one thread needs to modify it. So syncLock really is not suitable for this scenario. The correct way to do this is to implement locking if and only if a thread needs to modify the collection. I'll explain how to do this the old-fashioned way with mutexes and semaphores. The following procedure will ensure thread safe collection usage with minimal unneccessary locking. Execute the following steps to "write" protect a collection, i.e. when a thread intends to access the collection for modification. 1) When a thread wishes to modify the collection or it's members it must first acquire a mutex. The mutex is only available to one thread at any given time and is used to block all other threads from either read or write access to the collection. 2) After the "writer" thread acquires the mutex, it must wait until all other threads have released their semaphores which occurs when all other threads which are actively accessing the collection as "readers" have finished. 3) When all semaphores are signalled, the "writer" is ensured it is sole access to the collection and the collection or any of it's members may safely be modified because all other thre
Hi! Thx for the answers.I've used before semaphores and mutexes with C in linux.I wanted a quick way to make sure the concurrency doesn´t raise any problems. My really problem isn´t how the locking mechanism works, but a "second level" of locking.For example o use sockets read async.When i complete a read i have directly the object which i keep in the collection(along with many others).The thing is that at this point i need to lock just the object, not the entire collection.But when i'm enumerating the collection i lock it because i want to access all objects.So, i'm divided in how i should do that, because if i lock the collection but that in the read function have access to the object i'll be able to modify it!!!That's not right. Sugestions? Never say never
-
Hi! Thx for the answers.I've used before semaphores and mutexes with C in linux.I wanted a quick way to make sure the concurrency doesn´t raise any problems. My really problem isn´t how the locking mechanism works, but a "second level" of locking.For example o use sockets read async.When i complete a read i have directly the object which i keep in the collection(along with many others).The thing is that at this point i need to lock just the object, not the entire collection.But when i'm enumerating the collection i lock it because i want to access all objects.So, i'm divided in how i should do that, because if i lock the collection but that in the read function have access to the object i'll be able to modify it!!!That's not right. Sugestions? Never say never
Mutexes and Semaphores will still work. Keep in mind that mutexes and semaphores do not "lock" anything. They are just a means of inter-thread communications. A mutex says "I am in the process of modifying some object. No other threads should attempt to access this object until I am done". A semaphore says "I am in the process of accessing some object. No other threads should attempt to modify this object until I am done." The developer still has to write all the code that ensures each thread obeys the rules when accessing an object. carlos_rocha wrote: When i complete a read i have directly the object which i keep in the collection(along with many others).The thing is that at this point i need to lock just the object, not the entire collection.But when i'm enumerating the collection i lock it because i want to access all objects.So, i'm divided in how i should do that, because if i lock the collection but that in the read function have access to the object i'll be able to modify it!!!That's not right. You have to set a reference to the object somewhere. It does not matter if you are enumerating the collection or setting a reference directly to an object that exists in the collection. Before you access a member of the collection by any method of access - direct or by enumeration (both of which require you to set a reference to the object) the thread should acquire a semaphore to notify all other threads that it is accessing an object and they cannot modify any objects or the collection itrself. Before you attempt to modify either an object or the collection itself, a thread must acquire the mutex and wait for all semphores to become signalled. This means that no other thread is actively accessing any object in the collection. In this scenario, you are not sychronizing the objects themselves, you are synchronizing read and write operations on both the collection itself and all of it's members. This will work as long as you are not frequently modifying data either at the collection level or at the member object level. If you are frequently modifying member objects then you may find that synchronizing on read and write operations causes excessive wait times. In this case you have to implmement synchronization at two levels - collection add/deletes as a top level and per-object synchronization at the member level. This is a lot more complicated. Before I would implement this degree of synchronization I would carefully examine my application design. Mu
-
Mutexes and Semaphores will still work. Keep in mind that mutexes and semaphores do not "lock" anything. They are just a means of inter-thread communications. A mutex says "I am in the process of modifying some object. No other threads should attempt to access this object until I am done". A semaphore says "I am in the process of accessing some object. No other threads should attempt to modify this object until I am done." The developer still has to write all the code that ensures each thread obeys the rules when accessing an object. carlos_rocha wrote: When i complete a read i have directly the object which i keep in the collection(along with many others).The thing is that at this point i need to lock just the object, not the entire collection.But when i'm enumerating the collection i lock it because i want to access all objects.So, i'm divided in how i should do that, because if i lock the collection but that in the read function have access to the object i'll be able to modify it!!!That's not right. You have to set a reference to the object somewhere. It does not matter if you are enumerating the collection or setting a reference directly to an object that exists in the collection. Before you access a member of the collection by any method of access - direct or by enumeration (both of which require you to set a reference to the object) the thread should acquire a semaphore to notify all other threads that it is accessing an object and they cannot modify any objects or the collection itrself. Before you attempt to modify either an object or the collection itself, a thread must acquire the mutex and wait for all semphores to become signalled. This means that no other thread is actively accessing any object in the collection. In this scenario, you are not sychronizing the objects themselves, you are synchronizing read and write operations on both the collection itself and all of it's members. This will work as long as you are not frequently modifying data either at the collection level or at the member object level. If you are frequently modifying member objects then you may find that synchronizing on read and write operations causes excessive wait times. In this case you have to implmement synchronization at two levels - collection add/deletes as a top level and per-object synchronization at the member level. This is a lot more complicated. Before I would implement this degree of synchronization I would carefully examine my application design. Mu
Hi!Thanks on the great insight.I think the app is fairly well designed.My issue is that i have a thread that does some processing with one object and another thread (that enumerates the collection) is checking out the state of the objects.When the processing level determines that the object has reached the end of its life it changes its state and the cleanup thread (the one that enumerates the collection) deals with the object cleanup and removal.I'm trying to synchronize at these two levels. What about readerWriterLock? That was my second choice.Doesn´t this strategy ensures security for reads and writes like you said? If this isn't ok i'll use mutexes and semaphores. Note:i didn´t had so far any concurency issue but i'm sure that when i release the app for beta testing some will go wrong :-D Once again thanks for all the help. Never say never
-
Hi!Thanks on the great insight.I think the app is fairly well designed.My issue is that i have a thread that does some processing with one object and another thread (that enumerates the collection) is checking out the state of the objects.When the processing level determines that the object has reached the end of its life it changes its state and the cleanup thread (the one that enumerates the collection) deals with the object cleanup and removal.I'm trying to synchronize at these two levels. What about readerWriterLock? That was my second choice.Doesn´t this strategy ensures security for reads and writes like you said? If this isn't ok i'll use mutexes and semaphores. Note:i didn´t had so far any concurency issue but i'm sure that when i release the app for beta testing some will go wrong :-D Once again thanks for all the help. Never say never
ReaderWriterLock is a VB.NET class wrapper for mutexes and semaphores. The advantage is it makes code quicker to write. The disadavantage is that it obscures what is really happening. The fundamental synchronization technique is the same as using mutexes and semaphores directly. Robert