Optimize your Applications with Multithreading
A Well-Defined Order
The role of a developer is to define the various instructions that your computer will have to execute in order to complete a program. As it runs, your computer will read each of these instructions, and execute them one after the other. This is very important, because if just one of these instructions is wrong, your whole program will be impacted !
I suggest you to see this through an apparently simple example : The realization of a multiplayer mode in a video game. Our goal is to make different players appear on the same map, each of them being synchronized with the others via a database on a server. Each time the screen is refreshed, your computer will have to perform the following tasks :
• Display the game's background.
• Move the main player.
• Display the main player.
• Recover the positions of the other players.
• Display these other players.
• And finally, refresh the screen.
I propose to you to schematize this operation, to see more clearly.
In theory, each of these instructions is triggered once the previous one is completed, and so on for the duration of your game.
However, there is a problem with this type of operation : Each of these instructions takes a certain amount of time to execute, and this delay depends on the action you are going to perform. For example, a connection to the network to retrieve the position of a player is much longer than the display of that player.
Unfortunately, neither you nor I can influence this execution time, because it is intrinsically linked to your computer.
During this time, your computer cannot do anything, because it waits for the end of the current instruction. In the case of a memory access, the delay is so short that neither you nor your computer can do anything. But in the case of a longer operation, such as a connection to a server, it is possible that your computer could freeze for several hundred milliseconds, which is inconceivable if you don't want to scare your users away ! This is called synchronous execution.
Parallelize instructions
In a video game, or any website, the responsiveness of your application is a determining factor if you don't want to frustrate your users. So you can't accept that your computer waits unnecessarily for the end of an instruction without doing anything else. Since the problem comes from the chain of instructions, we will try to desynchronize them, so that they run in parallel, and not one after the other. In technical terms, this is called multithreading.
Simply said, a thread is a sequence of instructions that your computer will execute. When you develop an application, it is automatically placed in a single thread, and works as we saw above. But the point of multithreading is, as the name implies, to create several threads, corresponding to several instruction sequences. So we will create a new thread, and put in it the operations that slow down our main thread.
This will allow us to have a main thread that runs fast, and a second thread that runs slower, but does not slow down the main thread !
You will notice that all threads have a common goal : Update screen. To achieve this, it is necessary to give them one or more parameters related to this common goal. Here we can use a pointer referring to the screen.
This parameter is at the heart of multithreading. It allows each thread to run on its own, and at the speed it wants, and to update the screen as soon as it has completed its cycle.
Be careful though : Each thread must be independent of the rest of the program. For example, we can't parallelize the recovery of the player's position with his display, because the latter implies that we know his position, and therefore that the previous instruction is finished.
To help you understand this concept, I propose a small comparison with real life. Imagine a pizza player who bakes pizzas one by one in his oven. His working capacity is limited by the time it takes to bake a pizza, and if the oven were to break down, all production would be stopped. But if he decides to invest in a second oven, he will be able to do two services at the same time, and will be able to continue working even if one of the two ovens breaks down.
If you have understood this example, replace the pizzas by the instructions in your program, and the ovens by the different threads, and you will get a perfect example of how multithreading works !
Multithreading is Everywhere
I've given you an example of multithreading in video games, but you should know that its use is ubiquitous in any modern application. An example that you probably already used without even realizing it is the use of callback functions in JavaScript.
As a reminder, a callback function is a predetermined function, which is called in response to a given event. As far as this site goes, many callback functions are defined. Look at the button to subscribe to my Newsletter, and more precisely its JavaScript code :
$("#newsletterForm").submit(function(event) {
event.preventDefault();
alert("Merci de votre inscription !");
});
This is a callback function, which will be called when the form is submitted. Your browser will only execute this function when the form is sent and the user has entered his email address. Then, it will be enough to register this email address, (For example with an AJAX request) and thank the visitor for his registration.
What is the relationship between callback functions and threads ? Well, callback functions use threads to program their triggering. Without threads, JavaScript would have to manually check every millisecond the state of each event, and possibly call the appropriate functions that would block the user's navigation. Whereas here, your browser will simply create a thread for each callback function, specifying the requested event. Once this is activated, the function will be executed directly from the thread, which will not interfere with the rest of the program.
Finally, I told you about software threads, managed by your operating system. But in the last few years, we have seen the appearance of multi-core processors, which allow you to perform multi-threading in a hardware way. It would be a bit complicated to explain here, but it allows each core of your processor to supervise a different thread, for even faster overall operation.
Multithreading is a key concept in programming, and allows you to create different threads of execution. The result is a set of subprograms that run in parallel, in order to optimize the execution time of each operation. This principle has gained in popularity in recent years, and is nowadays extremely used in computer science, from programming networked video games to the operation of modern websites.
Écrit par Pythony le 26/01/2020.