Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to analyze the introduction of Multi-process, Multi-thread and Cooperative Program in Go language

2025-01-20 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/01 Report--

Go language how to analyze the introduction of multi-process, multi-threading and collaborative programs, many novices are not very clear about this, in order to help you solve this problem, the following editor will explain in detail for you, people with this need can come to learn, hope you can get something.

Why concurrent programming?

There is no concept of concurrency in native PHP, and all operations are executed serially and blocked synchronously, which is why many people criticize PHP performance, but the benefits of not supporting concurrent programming are also obvious: it ensures the simplicity of PHP, developers do not have to consider the thread safety introduced by concurrency, and do not need to weigh whether locking is needed to ensure the atomicity of an operation. There is no problem of communication between threads. You can't get both fish and bear's paw at the same time. In fact, the business and scenarios of more than 90% companies do not require such high performance at all. The traditional Nginx + PHP-FPM is completely competent. If you have to implement asynchronous and concurrent programming in PHP, it is recommended to use Swoole extensions to solve the problem (in fact, The cooperative programming function of Swoole draws lessons from the cooperative programming mechanism of Go language.

Next, let's return to the original book to introduce the concept and implementation of concurrent programming in the Go language.

The opposite of concurrency is serial, that is, the code is executed one by one in order. When you encounter a time-consuming IO operation, such as sending mail, querying a database, etc., you can not continue to execute the next line of code until the IO operation is completed. This is obviously not appropriate in some business scenarios that require high concurrency and high performance. From the whole operating system level, multiple tasks can be executed concurrently. Because CPU itself is usually multicore, and even a single-core CPU can switch between multiple processes / threads by time slicing, as if they were "happening at the same time" from the user's point of view, for example, when the program executes the IO operation, we can suspend the task, transfer the CPU time slice to other tasks, and then when the IO operation is complete Tell CPU to resume the execution of subsequent code, and CPU actually does this kind of scheduling most of the time. Therefore, concurrent programming can maximize the value of CPU and improve the execution efficiency and performance of the program.

Common implementation of concurrent programming

At present, the mainstream concurrent programming implementations have the following ways:

Multiple processes. Multi-process is the basic mode of concurrency at the operating system level, and it is also the most expensive mode. On the Linux platform, many tools work in this mode, such as PHP-FPM, which has a special main process responsible for network port listening and connection management, and multiple working processes are responsible for specific request processing. The advantage of this method is that it is simple and does not affect each other, while the disadvantage is that the system overhead is high, because all processes are managed by the kernel, and the data of different processes are isolated from each other.

Multithreading. Multithreading belongs to the concurrent mode at the system level on most operating systems, and it is also the most effective mode that we use most frequently. At present, almost all common tools use this mode, threads are lighter than processes, threads can share data, and the overhead is much less than that of multi-processes, but it is still relatively large, and efficiency will be affected in high concurrency mode, such as the C10K problem, that is, supporting 10,000 concurrent connections requires 10,000 threads, which not only requires higher system resources, but also brings a huge burden on CPU to manage these threads.

Non-blocking / asynchronous IO based on callback. In order to solve the C10K problem, in many highly concurrent server development practices, asynchronous IO is used in an event-driven way. In this mode, a thread can maintain multiple Socket connections, thus reducing system overhead and keeping the server running continuously. It has been well practiced in Node.js. In fact, Nginx also uses this method. But using this mode, programming is more complex than multithreading and usually needs to be implemented with the help of the underlying library functions of Linux.

Assist the journey. Coroutine is essentially a user-mode thread, you can think of it as a lightweight thread, do not need the operating system for preemptive scheduling, minimal system overhead, can effectively improve the task concurrency of threads and avoid the shortcomings of multi-threads. The advantage of using the cooperative program is simple programming and clear structure; the disadvantage is that it needs language-level support, if not, the user needs to implement the corresponding scheduler in the program. At present, there are few native languages to support the cooperative program, and the Go language is one of them. The cooperative program in the Go language is called "goroutine", and uses the language name itself go as the keyword of the cooperative program, which shows that it plays an important role in the Go language. PHP's Swoole extension also refers to the implementation of the Go protocol to move it to PHP.

The defects of traditional concurrency mode

Next, we first explain the shortcomings of the traditional concurrency model, and then explain how the goroutine concurrency model solves these defects. If you are only familiar with PHP programming and have not been exposed to concurrent programming, you need to digest these concepts and go back to Swoole after learning Go concurrent programming. Because multi-process consumes system resources and data is isolated between processes, the cost of CPU switching is high, so traditional concurrent programming is mainly multi-threaded, such as Java. Below we focus on the comparison of multithreading and collaboration.

Most of our previous programming in PHP is serial thinking, and serial transactions are deterministic. For example, when we think of 123, and then write the code in this order, the code will be executed strictly in this set order, and even if a certain step is blocked, we will always wait for the blocking code to finish, and then execute the next step.

The multithreaded concurrency pattern introduces uncertainty in this certainty, such as the 123 we originally set. Step 2 is a time-consuming operation, and we start a new thread to deal with it. At this time, there are two concurrent threads, that is, the original main thread and the new thread started in step 2, the main thread continues to execute later, and the code in steps 2 and 3 executes concurrently. We do not know whether the new thread has finished execution when the main thread finishes execution. If the main thread exits the application after execution, it may lead to the interruption of the new thread, or when we rely on some return result of step 2 in step 3, we do not know when we will be able to return this result. If steps 2 and 3 have interdependent variables, there may even be a deadlock. And how to get the exception and error information of the new thread in the main thread and deal with it accordingly, and so on, this uncertainty not only brings accident and harm to the behavior of the program, but also makes the program uncontrollable.

Different threads are like parallel time and space. We need to communicate the current status and results of different threads through communication between threads, so as to make the program controllable. Threads can communicate by sharing memory (refer to Swoole Table in Swoole), that is, the values stored on the same memory address are operated in different threads. In order to ensure the effectiveness of shared memory, many measures need to be taken, such as adding locks to avoid deadlock or resource competition, or taking the above main thread and new thread as an example, if we get an intermediate result in step 1, steps 2 and 3 have to operate on the intermediate result, if there is no lock to ensure the atomicity of the operation, dirty data is likely to be generated. Such problems are very likely to cause major failures or even accidents in the production environment, and are not easy to detect and debug.

We can call the way threads add shared memory a "shared memory system". In order to solve the problems of shared memory system, computer scientists put forward "message passing system". The so-called "message passing system" means that all kinds of operations of shared state between threads are encapsulated in messages transmitted between threads. this usually requires copying the state when sending the message and handing over the ownership of the state on the boundary of the message delivery. In terms of indication, this operation is the same as the atomic update operation performed by locking in the "shared memory system", but it is different from the underlying implementation: one operates on the value held by the same memory address. One is to read data from the message channel and process it. Because of the need to perform state replication operations, most messaging implementations are not superior in performance, but state management in threads becomes easier, which is a bit like what we mentioned at the beginning of PHP, which does not support concurrent programming. If you want to make coding simple, performance has to be sacrificed, and if you want to pursue performance, the code is more difficult to write. This is why we usually do not implement concurrent programming directly through event-driven asynchronous IO, because it involves directly calling the underlying library functions of the operating system (select, epoll, libevent, etc.), which is very complex.

Note: the earliest widely used "messaging system" was proposed by C. A. R. Hoare in his Communicating Sequential Processes. In CSP system, all concurrent operations are implemented by independent threads running asynchronously. These threads must request information from or provide information to another thread by sending messages to each other.

Go language cooperation program support

Compared with traditional system-level threads and processes, the biggest advantage of cooperative programs is that they are lightweight (can be regarded as lightweight threads in user mode). We can easily create millions of coprograms without causing system resource exhaustion. Threads and processes are usually no more than 10,000 (C10K problem). Most languages do not directly support cooperative programs at the syntax level, but through libraries, such as PHP's Swoole extension library, but the functions supported by libraries are usually incomplete, such as only providing the ability to create, destroy and switch lightweight threads. If you call a synchronous IO operation in such a lightweight thread, such as network communication, local file reading and writing, it will block other concurrent execution of lightweight threads, thus not really achieving the goal that the lightweight thread itself expects to achieve.

The Go language supports collaborative programs at the language level, called goroutine. All system call operations (and, of course, all synchronous IO operations) provided by the Go language standard library have the presence of a cooperative program. The management of handover between cooperators does not depend on the threads and processes of the system, nor on the number of CPU cores, which makes it very easy for us to realize concurrent programming through collaborations in Go language.

The cooperative programming system of Go language is based on "message passing system". In the programming philosophy of Go language, the founder Rob Pike recommended "Don't communicate by sharing memory, share memory by communicating (not to communicate through shared memory, but to share memory through communication)", which is the essence of "messaging system". Goroutine in Go language and channel, which is used to transmit messages between protocols, work together to build the cornerstone of Go language protocol system.

What go is suitable for go is the abbreviation of golang, while golang can do server-side development, and golang is very suitable for log processing, data packaging, virtual machine processing, database agent and other work. In the aspect of network programming, it is also widely used in web applications, API applications and other fields.

Is it helpful for you to read the above content? If you want to know more about the relevant knowledge or read more related articles, please follow the industry information channel, thank you for your support.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report