This is the first day of my participation in the Gwen Challenge in November. Check out the details: the last Gwen Challenge in 2021

History of concurrent programming

Concurrency Programming is a phrase that naturally conjures up two or more ideas. The emergence of concurrent programming is the result of the progress of computer hardware and operating system, as well as the result of the pursuit of faster and more efficient problem solving by computer science.

Before concurrency

Before concurrency, the execution of programs was naturally serial. Computers had single-core cpus and very little memory. The problems to be solved by computers were far less complex than they are now. Serializing programs solves a lot of problems.

With the development of computer software and hardware, not only a computer can have multiple cpus, a CPU can also have multiple cores. Memory is getting bigger and faster. In order to make full use of these resources, as well as improve the efficiency and cope with the larger amount of computation, the concurrent programming technology naturally emerged.

The basic concept of concurrency

Concurrency and parallelism

Concurrency and parallelism, although there is only a word difference, are actually very different concepts.

  • Concurrency is multiple threads doing the same thing:

    • These processes may not be related at all. For example, if we take the sum of N numbers, we can divide the N numbers into M parts, sum them separately with M threads, and then merge them with one thread. That’s concurrency.
  • Parallelism is when multiple processes do different things:

    • All a program does is find the sum of N numbers, whether it’s done by one thread or multiple threads.
    • What the other program does is take the product of N numbers, whether it’s done by one thread or multiple threads.
    • Both threads are scheduled by the same CPU in their respective areas of memory, and both programs run simultaneously. So this is parallelism.

In summary, concurrency is connected to each other and can share data, while parallelism is less connected to each other and doing different things that don’t share data.

Concurrent programming

One of the most important concepts involved by concurrency is Thread, the means of concurrency is multithreading, so concurrent programming can also be called multithreading programming, if there is no multithreading programming must not be called concurrent programming.

The execution unit of concurrent programming

The execution unit of concurrent programming, what are threads? Threads can be thought of as small – grained processes. The difference between threads and processes is that they share memory and processes have independent memory.

Serial and parallel

serial

The antonym of serial is parallel, serial can be understood as doing one thing at a time, from the micro level, CPU instruction execution must be serial, a clock cycle, a single CPU in a single core can not execute two instructions at the same time.

parallel

In parallel, as mentioned above, multiple processes do different things. From a micro point of view, a multi-core CPU or multiple cpus executing different instructions in the same clock cycle can be considered parallel.

Mononuclear and multicore

With the development of computer hardware, the gradual emergence of multi-core and even multi-CPU (macro can be multi-core and multi-CPU equivalent), so that concurrent programming naturally appeared.

In fact, this statement is, strictly speaking, anachronistic. Can not say that multi – core must be concurrent, single – core must only be serial. Single core can also be concurrent, multi – core nature can be absolutely serial.

Before multi-CPU (or multi-core), there was concurrency. It’s just that concurrency at this point is serialized at the micro level of instructions, and there must be only one thread running in a CPU clock cycle.

Therefore, the performance and efficiency of multithreaded programming is not necessarily higher than serial programming at this point. Of course, parallelism is naturally more efficient than serial.

For example, if a program is CPU intensive and is CPU intensive at one moment, and another program is IO intensive, it can be scheduled to perform IO computation at the same time without affecting the CPU intensive program, thus naturally improving efficiency.

Single core can be concurrent or parallel, and concurrent programming in multi-core scenarios is much more efficient than single core. Here’s an Amdar’s law to illustrate this. Amdar’s law.

The impact of concurrent programming

Obviously, the biggest impact of concurrent programming is increased efficiency and utilization of computing resources (parallelism is also about utilization of computing resources). But concurrent programming also has a huge effect, which is that it makes it harder to write concurrent programs. Writing the right programs is hard enough, but writing the right programs is even harder.

Why is it harder to write concurrent programs? The reason is that concurrent programs need to deal with thread scheduling, data sharing issues. Because of thread safety issues with data sharing.

At the same time, multi-threading means the need for additional scheduling logic, which leads to thread context switching and other losses. So multithreading is not a recipe for high performance. Using multithreading properly and carefully writing concurrent programs is the solution.

Sometimes, we can’t even ignore the performance degradation caused by thread switching, and we can’t tolerate the problem of thread safety resulting in incorrect calculation results caused by multithreading.

Does it increase computational efficiency

Multithreading is not the best way to achieve high performance. It can be said that the purpose of multithreading is to make full use of computer hardware resources and software resources, so that it is constantly in a busy state to improve production efficiency. High-performance solutions, however, sometimes require a broader approach.

Distributed architecture

Distributed architecture should be popular on the Internet these days. Because solving high concurrency, high traffic problems is often distributed. Microservices, now popular, can also be understood as a more granular SOA. In computer science or in real life, the way we solve big problems is to break them down. Break down big problems into small problems and big modules into small modules. Then use multi-instance, multi-service solution. For this reason, at the macro level, the ideas of distribution and concurrency are somewhat compatible. They are all small and big, broken down one by one.

coroutines

Multithreading inevitably leads to the problem of thread switching. Thread switching consumes additional computing resources. So we have a coroutine in computer science. Threads can be thought of as small-grained processes, and coroutines can be thought of as small-grained threads. Coroutines do not require a context switch, and calling other methods in a method call does not require a resource switch. The key here is to take advantage of CPU interrupts. Therefore, the resource consumption caused by thread switching is avoided. In the future, Java will definitely support coroutines. Coroutines are already supported in Python.

Java concurrency programming basic means

Java multithreading means and basic usage (Thread,Runnable,Callable), static,final and other Thread safety significance

Thread safety and thread communication issues

Introduce critical sections, data contention, and thread communication models, and delve into thread communication methods (analyzing ThreadLocal classes) and their implications

Atomicity and visibility

Because multithreaded communication problems, may cause problems such as atomicity and visibility, from the Java language level explain atomicity and visibility

Java Memory Model (JMM)

Dig deeper to understand the JMM, and to understand synchronized and volatile from a JMM perspective

J.U.C overview

JDK concurrent toolkit introduction, from the structure and function of the package to do an overview, for the following decomposition of paving the way

Lock deep in J.U.C

The locking mechanism and implementation principle provided by Java language level are deeply analyzed, and the similarities and differences of synchronized are compared

Dive into the Executor framework in J.U.C

An in-depth analysis of thread pools in Java, and a comparative analysis of the similarities and differences and usage of thread pools in 4

Delve into the concurrent container class in J.U.C

Briefly analyze the functions and usage of each container class, focusing on ConcurrentHashMap

Dive into the J.U.C subclass

It simply analyzes the usage and functions of various atomic classes, focusing on the realization and underlying mechanism of CAS operation

Delve into the concurrency utility classes in J.U.C

Briefly analyze the usage and functions of each tool class, focusing on CountDownLatch and CyclicBarrier

Summary of Concurrent programming

This idea from simple to complex, is basically in accordance with the idea of concurrent programming learning. Of course, the chapters stand alone. Can be used as a separate review or study reference. I hope this topic can bring me and others to sort out and consolidate knowledge.