Concurrent Collections
1 Why use concurrent collections?
The main reasons are as follows:
-
The classic lists, collections, and arrays provided in the System.Collections and System.Collections.Generic namespaces are not thread-safe, and if there is no synchronization mechanism, they are not suitable for accepting concurrent instructions to add and remove elements.
-
The use of these classic collections in concurrent code requires complex synchronization management, which is inconvenient to use.
-
Using a complex synchronization mechanism can greatly degrade performance.
-
NET Framework 4 provides a new collection as much as possible to reduce the number of times a lock needs to be used. These new collections avoid the use of mutually exclusive heavyweight locks by using the Compare and Exchange (COMPARE-AND-SWAP,CAS) directives and memory barriers. This is guaranteed for performance.
Note: Concurrent collections are more expensive than classic collections, so using concurrent collections in serial code is meaningless, only adding additional overhead and running slower than accessing classic collections.
2 Concurrent Collections
1) Concurrentqueue: Thread-safe FIFO (FIFO) collection
Main methods:
-
Enqueue (T item); Adds an object to the end of the collection.
-
Trydequeue (out T result); Attempts to remove and return the object at the beginning of the collection, indicating whether the operation was successful.
-
Trypeek (out T result), attempts to return the object at the beginning of the collection, but does not remove it, and the return value indicates whether the operation was successful.
Description
-
The Concurrentqueue is completely unlocked, but it may spin and retry operations when the CAS operation fails and faces resource contention.
-
Concurrentqueue is a FIFO set, and some situations unrelated to the order of entry and exit, try not to use Concurrentqueue.
2) Concurrentstack: Thread-safe last-in-first-out (LIFO) collection
Main Methods and properties:
-
Push (T item), inserting the object at the top of the collection.
-
Trypop (out T result), an attempt to eject and return the object at the top of the collection, indicating whether the operation was successful.
-
Trypeek (out T result), attempts to return the object at the beginning of the collection, but does not remove it, and the return value indicates whether the operation was successful.
-
IsEmpty {get;} Indicates whether the collection is empty.
-
PushRange (t[] items); Inserts multiple objects at the top of the collection.
-
TryPopRange (t[] items), top multiple elements, return the result is the number of pop-up elements.
Description
-
Similarly to Concurrentqueue, the Concurrentstack is completely unlocked, but when the CAS operation fails and faces resource contention, it may spin and retry the operation.
-
Gets whether the collection contains elements using the IsEmpty property, rather than by determining whether the Count property is greater than 0. Calling count is larger than calling IsEmpty overhead.
-
Use PushRange (t[] items) and TryPopRange (t[] items) to pay attention to the additional overhead and additional memory consumption caused by buffering.
3) Concurrentbag: An unordered set of elements that can be duplicated
Main Methods and properties:
-
Trypeek (out T result), attempting to return an object from the collection, but not removing the object, the return value indicates whether the object was successfully obtained.
-
TryTake (out T result), attempting to return an object from the collection and removing the object, the return value indicates whether the object was successfully obtained.
-
Add (T Item), adding the object to the collection.
-
IsEmpty {get;} Explain the same concurrentstack
Description
-
Concurrentbag maintains a local queue for each thread that accesses the collection, and, where possible, it accesses the local queue in a lock-free manner.
-
Concurrentbag is very efficient in situations where elements are added and removed from the same thread.
-
Because concurrentbag sometimes require locks, it is very inefficient in scenarios where producer and consumer threads are completely separated.
-
Concurrentbag calling IsEmpty is expensive because it requires temporary access to all locks for this unordered group.
4) BlockingCollection: Realization
System.collections.concurrent.iproducerconsumercollection<t> Thread-Safe collection that provides blocking and throttling capabilities
Main Methods and properties:
-
BlockingCollection (int boundedcapacity); boundedcapacity represents the collection limit size.
-
CompleteAdding (); Mark the BlockingCollection instance as no longer accepting any additions.
-
iscompleted {get;} Whether this collection has been marked as finished added and is empty.
-
GetConsumingEnumerable (); Remove and return the removed element from the collection
-
Add (T Item), adding elements to the collection.
-
TryTake (T item, int millisecondstimeout, CancellationToken cancellationtoken);
Description
-
Instantiating BlockingCollection with the BlockingCollection () constructor means that boundedcapacity is not set, then boundedcapacity is the default value: Int. MaxValue.
-
Gauge: Using blockingcollection (int boundedcapacity), set the value of Boundedcapacity, when the collection capacity reaches this worth, the thread that adds elements to the BlockingCollection will be blocked, Until an element has been deleted.
The gauge function controls the maximum size of the collection in memory, which is useful when you need to handle a large number of elements.
-
By default, BlockingCollection encapsulates a concurrentqueue. You can specify a concurrent collection in the constructor that implements the Iproducerconsumercollection interface, including: Concurrentstack, Concurrentbag.
-
Using this collection contains risks that are easy to wait indefinitely, so use trytake more because TryTake provides time-out control, which is true if an item can be removed from the collection within the specified time;
5) Concurrentdictionary: A thread-safe collection of key-value pairs that can be accessed concurrently by multiple threads.
Main methods
AddOrUpdate (TKey key, TValue addvalue, Func<tkey, TValue, tvalue> updatevaluefactory); If the specified key does not already exist, add a key/value pair to the dictionary If the specified key already exists, the key/value pair in the dictionary is updated.
-
Getoradd (TKey key, TValue value), or the key/value pair is added to the dictionary if the specified key does not already exist.
-
Tryremove (TKey key, out TValue value), attempts to remove from the dictionary and returns a value with the specified key.
-
Tryupdate (TKey key, TValue newvalue, TValue comparisonvalue); Compares the existing value of the specified key to the specified value, and if it is equal, updates the key with the third value.
Description
6) Iproducerconsumercollection: Defines a method for the producer/consumer to manipulate the thread-safe collection. This interface provides a uniform representation (for producer/consumer collections), thus higher level abstractions such as system.collections.concurrent.blockingcollection<t> can use the collection as the underlying storage mechanism.
3. Common mode
1) Parallel producer-consumer model
Defined:
The producer and consumer are two types of object models in this pattern, consumers rely on the results of the producers, and the producers produce results while the consumer uses the results.
Figure 1 parallel producer-consumer model
Description
-
Concurrent collections are appropriate in this mode because concurrent collections support parallel operations of objects in this pattern.
-
If you do not use concurrent collections, you need to join the synchronization mechanism, which makes the program more complex, difficult to maintain and understand, and greatly reduces performance.
-
For the producer consumer model, the vertical axis is the timeline, and the generator and the consumer are not on a timeline, but there is a crossover, which is intended to show that the producer produces the result first, and then the consumer actually uses the data generated by the creator.
2) Pipeline Mode
Defined:
The pipeline is composed of several stages, each of which is composed of a series of producers and consumers. In general, the previous phase is the generator of the latter phase, and each stage can be executed concurrently by relying on the buffer queue between the two adjacent phases.
Figure 2 Parallel pipelined mode
Description
-
Blockingcollection<t> is often used as a buffer tank area queue.
-
The speed of the pipeline is approximately equal to the speed of the slowest stage of the pipeline.
-
For pipelining, the previous stage is the next generation, where the simplest and most basic pipelining patterns are shown, and more complex patterns can be considered to include more processing of data at each stage.
4 How to use
In the case of Concurrentbag and BlockingCollection alone, other concurrent collections are similar.
Concurrentbag
List <string> list = ......
ConcurrentBag <string> bags = new ConcurrentBag <string> ();
Parallel.ForEach (list, (item) =>
{
// Process each element in the list and add it to bags
bags.Add (itemAfter);
});
blockingcollection-Producer Consumer Model
public static void Execute ()
{
// Call Invoke to make the producer task and consumer task execute in parallel
// Producer method and Customer method in Invoke parameter order is arbitrary, no matter what order will get the correct result
Parallel.Invoke (() => Customer (), () => Producer ());
Console.WriteLine (string.Join (",", customerColl));
}
// Producer set
private static BlockingCollection <int> producerColl = new BlockingCollection <int> ();
// Consumer collection
private static BlockingCollection <string> customerColl = new BlockingCollection <string> ();
public static void Producer ()
{
// Cycle add data to the generator set
for (int i = 0; i <100; i ++)
{
producerColl.Add (i);
}
// Set the signal to indicate that no new data is added to the producer collection
// You can set a more complex notification form, such as when the amount of data reaches a certain value and the data in it meets a certain condition, the setting is added
producerColl.CompleteAdding ();
}
public static void Customer ()
{
// Call the IsCompleted method to determine whether the producer collection is adding data, and whether there is data that is not "consumed"
// Be careful not to use IsAddingCompleted, IsAddingCompleted only indicates that the collection is marked as completed, not empty
// When IsCompleted is ture, then IsAddingCompleted is ture and the collection is empty
while (! producerColl.IsCompleted)
{
// Call Take or TryTake "consumption" data, consume one, remove one
// The advantage of TryAdd is to provide a timeout mechanism
customerColl.Add (string.Format ("Consumer: {0}", producerColl.Take ()));
}
}
The above is. NET multithreaded Programming-the contents of concurrent collections, for more information please follow topic.alibabacloud.com (www.php.cn)!