📜 ⬆️ ⬇️

Overview of threading models

Overview of threading models


Many people do not understand how multithreading is implemented in various programming languages. In our times, multi-core processors such knowledge will be very useful.
Here is a small review.

Start (C and native threads)

The first model that we will consider is the standard OS threads. They are supported by every modern OS, despite the difference in the API. In principle, a thread is a process of executing instructions that runs on a dedicated processor, the execution of which is controlled by the OS scheduler and which can be blocked. Threads are created internally and share resources. This means that, for example, memory and file descriptors are common to all threads of a process. This approach is called native threads.

Linux allows you to use data streams using the pthread library. BSDs also support pthreads. Windows threads work a little differently, but the basic principle is the same.

Java and Green Threads

When Java appeared, it brought with it a different type of multithreading called green threads. Green threads are essentially imitation threads. The Java virtual machine takes care of switching between different green threads, and the machine itself works as one OS thread. This gives several advantages. OS threads are relatively expensive in most POSIX systems. In addition, switching between native threads is much slower than between green threads.
')
This all means that in some situations, green threads are much more profitable than native threads. The system can support much more green threads than OS threads. For example, it is much more practical to run a new green thread for a new HTTP connection to a web server, instead of creating a new native thread.

However, there are disadvantages. The biggest one is that you cannot execute two threads at the same time. Since there is only one native thread, only it is called by the OS scheduler. Even if you have several processors and several green threads, only one processor can cause green thread. And all because from the point of view of the OS Task Scheduler, it all looks like one thread.

Starting with version 1.2, Java supports native threads, and since then they are used by default.

Python

Python is one of my favorite scripting languages ​​and was one of the first to work with streams. Python includes a module that allows you to manipulate native threads, so it can use all the benefits of true multithreading. But there is one problem.

Python uses a global interpreter lock (Global Interpreter Lock, GIL). This lock is necessary so that the threads cannot spoil the global state of the interpreter. Therefore, two Python instructions cannot be executed at the same time. GIL is removed approximately every 100 instructions and at this point another thread can intercept the lock and continue its execution.

At first this may seem a serious drawback, but in practice the problem is not so great. Any blocked thread usually releases GIL. Extensions C also release it when they do not interact with the Python / C API, so intensive calculations can be transferred to C and avoid blocking running Python threads. The only situation where GIL is really a problem is the situation when the Python thread tries to run on a multi-core machine.

Stackless Python is a version of Python that adds “tasklets” (actually green threads). For their reasons, the greenlet module was created, which is compatible with the de facto standard: cPython.

Ruby

The Ruby thread model is constantly changing. Initially, Ruby supported only its own version of green threads. This works well in many scenarios, but does not allow using multiprocessing capabilities.

JRuby translated Ruby streams into standard Java streams, which we figured out above are native threads. And this created problems. Ruby streams do not need to synchronize mutually. Each thread is guaranteed that no other thread will gain access to the shared resource being used. This behavior was broken in JRuby, since native threads are forced to switch (preemptive) and therefore any thread can access a shared resource at an arbitrary time.

Because of this inconsistency and the desire to get native threads by C Ruby developers, it was decided that Ruby will migrate to them in version 2.0. Ruby 1.9 included a new interpreter that added support for fibers, which, as far as I know, are a more efficient version of green threads.

In short, the Ruby threading model is a poorly documented mess.

Perl

Perl offers an interesting model that Mozilla borrowed for SpiderMonkey, if I'm not mistaken. Instead of using global interpreter locking as in Python, Perl made the global state local and actually launches a new interpreter for each new thread. This allows you to use real native threads. Not without a couple of snags.

First, you must explicitly specify variables that are accessible to other threads. This is what happens when everything becomes local to the stream. You have to synchronize values ​​for inter-thread communication.

Secondly, the creation of a new stream has become a very expensive operation. The interpreter is a big thing and multiple copying it eats up a lot of resources.

Erlang, JavaScript, C # and so on

There are many other models that are used from time to time. For example, Erlang, uses the “shared nothing” architecture, which encourages the use of light user processes instead of threads. This kind of architecture is great for parallel programming, as it eliminates all the headaches about synchronization, and the processes are so easy that you can create any number of them.

JavaScript is usually not perceived as a language that supports streaming, but it is also needed there. The threading model in JavaScript is very similar to the one used in Perl.

C # uses native threads.

From myself: I am annoyed with some superficiality of the article (which I myself realize) address to the author. I just translated into the best of my modest possibilities. ;) I will be glad clarifications and additions in the comments.

From myself 2: based on comments after a few corrected phrases. Sorry, author! :)

Source: https://habr.com/ru/post/39543/


All Articles