- Multithreading with C# Cookbook(Second Edition)
- Eugene Agafonov
- 517字
- 2021-07-09 19:35:37
Introduction
As we saw in Chapter 1, Threading Basics, it is problematic to use a shared object simultaneously from several threads. However, it is very important to synchronize those threads so that they perform operations on that shared object in a proper sequence. In the Locking with a C# lock keyword recipe, we faced a problem called the race condition. The problem occurred because the execution of those multiple threads was not synchronized properly. When one thread performs increment and decrement operations, the other threads must wait for their turn. Organizing threads in such a way is often referred to as thread synchronization.
There are several ways to achieve thread synchronization. First, if there is no shared object, there is no need for synchronization at all. Surprisingly, it is very often the case that we can get rid of complex synchronization constructs by just redesigning our program and removing a shared state. If possible, just avoid using a single object from several threads.
If we must have a shared state, the second approach is to use only atomic operations. This means that an operation takes a single quantum of time and completes at once, so no other thread can perform another operation until the first operation is complete. Therefore, there is no need to make other threads wait for this operation to complete and there is no need to use locks; this in turn, excludes the deadlock situation.
If this is not possible and the program's logic is more complicated, then we have to use different constructs to coordinate threads. One group of these constructs puts a waiting thread into a blocked
state. In a blocked
state, a thread uses as little CPU time as possible. However, this means that it will include at least one so-called context switch—the thread scheduler of an operating system will save the waiting thread's state and switch to another thread, restoring its state by turn. This takes a considerable amount of resources; however, if the thread is going to be suspended for a long time, it is good. These kind of constructs are also called kernel-mode constructs because only the kernel of an operating system is able to stop a thread from using CPU time.
In case, we have to wait for a short period of time, it is better to simply wait than switch the thread to a blocked
state. This will save us the context switch at the cost of some wasted CPU time while the thread is waiting. Such constructs are referred to as user-mode constructs. They are very lightweight and fast, but they waste a lot of CPU time in case a thread has to wait for long.
To use the best of both worlds, there are hybrid constructs; these try to use user-mode waiting first, and then, if a thread waits long enough, it switches to the blocked
state, saving CPU resources.
In this chapter, we will look through the aspects of thread synchronization. We will cover how to perform atomic operations and how to use the existing synchronization constructs included in .NET Framework.
- 小程序實戰視頻課:微信小程序開發全案精講
- 程序員面試筆試寶典
- Web Scraping with Python
- AngularJS Web Application Development Blueprints
- Java程序員面試算法寶典
- MySQL數據庫基礎實例教程(微課版)
- Visual C#.NET程序設計
- Learning Unreal Engine Android Game Development
- 機器學習微積分一本通(Python版)
- 實戰Java高并發程序設計(第2版)
- Zabbix Performance Tuning
- INSTANT JQuery Flot Visual Data Analysis
- Python網絡爬蟲實例教程(視頻講解版)
- Java Web動態網站開發(第2版·微課版)
- Elasticsearch實戰(第2版)