Home Backend Development C#.Net Tutorial .NET multi-threaded programming—concurrent collections

.NET multi-threaded programming—concurrent collections

Feb 06, 2017 pm 02:29 PM

Concurrent Collection

1 Why use concurrent collection?

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 Without a synchronization mechanism, they are not suitable for accepting concurrent instructions to add and remove elements.

  • Using the above classic collections in concurrent code requires complex synchronization management, which is very inconvenient to use.

  • Using complex synchronization mechanisms will greatly reduce performance.

  • The new collections provided by NET Framework 4 minimize the number of times you need to use locks. These new collections avoid the use of mutually exclusive heavyweight locks by using compare-and-swap (CAS) instructions and memory barriers. This guarantees performance.

Note: Compared with classic collections, concurrent collections will have greater overhead, so using concurrent collections in serial code is meaningless and will only increase additional overhead and run speed. Slower than accessing the classic collection.

2 Concurrent collection

1) ConcurrentQueue: thread-safe first-in-first-out (FIFO) collection

Main method:

  • Enqueue(T item);Adds the object to the end of the collection.

  • TryDequeue(out T result); Try to remove and return the object at the beginning of the collection. The return value indicates whether the operation was successful.

  • TryPeek(out T result); Try to return the object at the beginning of the collection without removing it. The return value indicates whether the operation was successful.

Note:

  • ConcurrentQueue is completely lock-free, but when a CAS operation fails and faces resource contention, it may spin and Retry the operation.

  • ConcurrentQueue is a FIFO collection. In some situations that have nothing to do with 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);Inserts the object at the top of the collection.

  • TryPop(out T result); Try to pop and return the object at the top of the collection. The return value indicates whether the operation is successful.

  • TryPeek(out T result); Try to return the object at the beginning of the collection without removing it. The return value indicates whether the operation was successful.

  • IsEmpty { get; } Indicates whether the collection is empty.

  • PushRange(T[] items);Insert multiple objects at the top of the collection.

  • TryPopRange(T[] items); Pops multiple elements at the top, and the return result is the number of popped elements.

Note:

  • Similar to ConcurrentQueue, ConcurrentStack is completely lock-free, but when the CAS operation fails and faces resource contention, it may Will spin and retry the operation.

  • Get whether the collection contains elements using the IsEmpty property instead of judging whether the Count property is greater than zero. Calling Count is more expensive than calling IsEmpty.

  • When using PushRange(T[] items) and TryPopRange(T[] items), pay attention to the extra overhead and extra memory consumption caused by buffering.

3) ConcurrentBag: an unordered collection with repeatable elements

Main methods and attributes:

  • TryPeek(out T result); attempts to return an object from the collection without removing the object. The return value indicates whether the object was successfully obtained.

  • TryTake(out T result); Try to return an object from the collection and remove the object. The return value indicates whether the object was successfully obtained.

  • Add(T item); Add the object to the collection.

  • IsEmpty { get; }The explanation is the same as ConcurrentStack

##Instructions:

  • ConcurrentBag is for each The thread accessing the collection maintains a local queue and, when possible, accesses the local queue in a lock-free manner.

  • ConcurrentBag is very efficient when adding and removing elements in the same thread.

  • Because ConcurrentBag sometimes requires locks, it is very inefficient in scenarios where producer threads and consumer threads are completely separated.

  • ConcurrentBag's call to IsEmpty is very expensive because it requires temporarily acquiring all the locks of this unordered group.

4) BlockingCollection: A thread-safe collection that implements

System.Collections.Concurrent.IProducerConsumerCollection, providing blocking and limiting functions

Mainly Methods and properties:

  • BlockingCollection(int boundedCapacity); boundedCapacity represents the collection limit size.

  • CompleteAdding(); Marks the BlockingCollection instance as no longer accepting any additions.

  • IsCompleted { get; } Whether this collection has been marked as completed and empty.

  • GetConsumingEnumerable();Removes from the collection and returns the removed element

  • Add(T item);Adds an element to the collection.

  • TryTake(T item, int millisecondsTimeout, CancellationToken cancellationToken);

Instructions:

  • Use BlockingCollection( ) constructor instantiates BlockingCollection, which means boundedCapacity is not set, then boundedCapacity is the default value: int.MaxValue.

  • Bound: Use BlockingCollection(int boundedCapacity) to set the value of boundedCapacity. When the collection capacity reaches this value, the thread that adds elements to BlockingCollection will be blocked until an element is deleted. .

The bounding function controls the maximum size of the collection in memory, which is very useful when a large number of elements need to be processed.

  • By default, BlockingCollection encapsulates a ConcurrentQueue. You can specify a concurrent collection that implements the IProducerConsumerCollection interface in the constructor, including: ConcurrentStack and ConcurrentBag.

  • Using this collection involves the risk of waiting indefinitely, so it is more convenient to use TryTake because TryTake provides timeout control and an item can be removed from the collection within a specified time. is true; otherwise, it is false.

5) ConcurrentDictionary: A thread-safe collection of key-value pairs that can be accessed by multiple threads simultaneously.

Main method

AddOrUpdate(TKey key, TValue addValue, Func updateValueFactory); If the specified key does not exist yet, add the key/value pair to the dictionary Medium; if the specified key already exists, updates the key/value pair in the dictionary.

  • GetOrAdd(TKey key, TValue value); If the specified key does not exist yet, adds the key/value pair to the dictionary.

  • TryRemove(TKey key, out TValue value);Try to remove from the dictionary and return the value with the specified key.

  • TryUpdate(TKey key, TValue newValue, TValue comparisonValue); Compares the existing value of the specified key with the specified value. If equal, updates the key with the third value.

Note:

  • ConcurrentDictionary is completely lock-free for read operations. ConcurrentDictionary uses fine-grained locks when multiple tasks or threads add elements or modify data to it. Using fine-grained locks only locks the part that really needs to be locked, not the entire dictionary.

6) IProducerConsumerCollection: Defines methods for producers/consumers to operate thread-safe collections. This interface provides a unified representation (for producer/consumer collections) so that higher level abstractions such as System.Collections.Concurrent.BlockingCollection can use collections as the underlying storage mechanism.

3. Commonly used patterns

1) Parallel producer-consumer pattern

Definition:

The producer and consumer are in this pattern Two types of object models, the consumer depends on the results of the producer, while the producer generates the results, the consumer uses the results.

.NET multi-threaded programming—concurrent collections

Figure 1 Parallel producer-consumer model

Description:

  • Concurrent collections are used here pattern is a good fit because concurrent collections support parallel operations on objects in this pattern.

  • If you do not use concurrent collections, you must add a synchronization mechanism, which will make the program more complex, difficult to maintain and understand, and greatly reduce performance.

  • The above picture is a schematic diagram of the producer-consumer model. The vertical axis is the timeline. The producer and the consumer are not on the same timeline, but they overlap, which is intended to show that The generator first produces results, and then the consumer actually uses the data generated by the generator.

2) Pipeline pattern

Definition:

The pipeline consists of multiple stages, each stage consists of a series of producers and consumers . Generally speaking, the previous stage is the generator of the later stage; relying on the buffer queue between two adjacent stages, each stage can be executed concurrently.

.NET multi-threaded programming—concurrent collections

Figure 2 Parallel pipeline mode

Description:

  • BlockingCollection is often used as a buffer tank Zone queue.

  • The speed of the pipeline is approximately equal to the speed of the slowest stage of the pipeline.

  • The above picture is a schematic diagram of the pipeline mode. The previous stage is the generator of the later stage. The simplest and basic pipeline mode is shown here. More complex modes can be considered as each Each stage includes more processing of the data.

4 How to use

Only take ConcurrentBag and BlockingCollection as examples, other concurrent collections are similar.

ConcurrentBag

List<string> list = ......
ConcurrentBag<string> bags = new ConcurrentBag<string>();
Parallel.ForEach(list, (item) => 
{
    //对list中的每个元素进行处理然后,加入bags中
    bags.Add(itemAfter);
});
Copy after login

BlockingCollection—Producer Consumer Pattern

public static void Execute()
{
            //调用Invoke,使得生产者任务和消费者任务并行执行
            //Producer方法和Customer方法在Invoke中的参数顺序任意,不论何种顺序都会获得正确的结果
            Parallel.Invoke(()=>Customer(),()=>Producer());
            Console.WriteLine(string.Join(",",customerColl));
}
//生产者集合
private static BlockingCollection<int> producerColl = new BlockingCollection<int>();
 //消费者集合
private static BlockingCollection<string> customerColl = new BlockingCollection<string>();
public static void Producer()
{
            //循环将数据加入生成者集合
            for (int i = 0; i < 100; i++)
            {
                producerColl.Add(i);
            }
            //设置信号,表明不在向生产者集合中加入新数据
            //可以设置更加复杂的通知形式,比如数据量达到一定值且其中的数据满足某一条件时就设置完成添加
            producerColl.CompleteAdding();
}
public static void Customer()
{
            //调用IsCompleted方法,判断生产者集合是否在添加数据,是否还有未"消费"的数据
            //注意不要使用IsAddingCompleted,IsAddingCompleted只表明集合标记为已完成添加,而不能说明其为空
            //而IsCompleted为ture时,那么IsAddingCompleted为ture且集合为空
            while (!producerColl.IsCompleted)
            {
                //调用Take或TryTake "消费"数据,消费一个,移除一个
                //TryAdd的好处是提供超时机制
                customerColl.Add(string.Format("消费:{0}", producerColl.Take()));
            }
}
Copy after login


The above is the content of .NET multi-thread programming - concurrent collection. For more related content, please pay attention to the PHP Chinese website (www.php.cn)!


Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Roblox: Bubble Gum Simulator Infinity - How To Get And Use Royal Keys
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Fusion System, Explained
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers Of The Witch Tree - How To Unlock The Grappling Hook
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

Java Tutorial
1665
14
PHP Tutorial
1270
29
C# Tutorial
1249
24
What are the advantages of using C++ lambda expressions for multi-threaded programming? What are the advantages of using C++ lambda expressions for multi-threaded programming? Apr 17, 2024 pm 05:24 PM

The advantages of lambda expressions in C++ multi-threaded programming include simplicity, flexibility, ease of parameter passing, and parallelism. Practical case: Use lambda expressions to create multi-threads and print thread IDs in different threads, demonstrating the simplicity and ease of use of this method.

Asynchronous processing solutions in Java API development Asynchronous processing solutions in Java API development Jun 18, 2023 am 10:11 AM

With the continuous development of Java technology, Java API has become one of the mainstream solutions developed by many enterprises. During the development process of Java API, a large number of requests and data often need to be processed, but the traditional synchronous processing method cannot meet the needs of high concurrency and high throughput. Therefore, asynchronous processing has become one of the important solutions in JavaAPI development. This article will introduce asynchronous processing solutions commonly used in Java API development and how to use them. 1. Java differences

C# development considerations: multi-threaded programming and concurrency control C# development considerations: multi-threaded programming and concurrency control Nov 22, 2023 pm 01:26 PM

In C# development, multi-threaded programming and concurrency control are particularly important in the face of growing data and tasks. This article will introduce some matters that need to be paid attention to in C# development from two aspects: multi-threaded programming and concurrency control. 1. Multi-threaded programming Multi-threaded programming is a technology that uses multi-core resources of the CPU to improve program efficiency. In C# programs, multi-thread programming can be implemented using Thread class, ThreadPool class, Task class and Async/Await. But when doing multi-threaded programming

Share several .NET open source AI and LLM related project frameworks Share several .NET open source AI and LLM related project frameworks May 06, 2024 pm 04:43 PM

The development of artificial intelligence (AI) technologies is in full swing today, and they have shown great potential and influence in various fields. Today Dayao will share with you 4 .NET open source AI model LLM related project frameworks, hoping to provide you with some reference. https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.mdSemanticKernelSemanticKernel is an open source software development kit (SDK) designed to integrate large language models (LLM) such as OpenAI, Azure

What is the purpose of read-write locks in C++ multi-threaded programming? What is the purpose of read-write locks in C++ multi-threaded programming? Jun 03, 2024 am 11:16 AM

In multi-threading, read-write locks allow multiple threads to read data at the same time, but only allow one thread to write data to improve concurrency and data consistency. The std::shared_mutex class in C++ provides the following member functions: lock(): Gets write access and succeeds when no other thread holds the read or write lock. lock_read(): Obtain read access permission, which can be held simultaneously with other read locks or write locks. unlock(): Release write access permission. unlock_shared(): Release read access permission.

How to implement C++ multi-thread programming based on the Actor model? How to implement C++ multi-thread programming based on the Actor model? Jun 05, 2024 am 11:49 AM

C++ multi-threaded programming implementation based on the Actor model: Create an Actor class that represents an independent entity. Set the message queue where messages are stored. Defines the method for an Actor to receive and process messages from the queue. Create Actor objects and start threads to run them. Send messages to Actors via the message queue. This approach provides high concurrency, scalability, and isolation, making it ideal for applications that need to handle large numbers of parallel tasks.

What are the employment prospects of C#? What are the employment prospects of C#? Oct 19, 2023 am 11:02 AM

Whether you are a beginner or an experienced professional, mastering C# will pave the way for your career.

How to use multi-threaded programming in PHP? How to use multi-threaded programming in PHP? May 12, 2023 am 08:39 AM

As web applications become larger and more complex, the traditional single-threaded PHP development model is no longer suitable for high concurrency processing. In this case, using multi-threading technology can improve the web application's ability to handle concurrent requests. This article will introduce how to use multi-threaded programming in PHP. 1. Overview of Multithreading Multithreaded programming refers to the concurrent execution of multiple threads in a process, and each thread can independently access shared memory and resources in the process. Multi-threading technology can improve CPU and memory usage efficiency, and can handle more

See all articles