Java concurrency foundation summary

Concurrency is the ability to run multiple programs or parts of a program in parallel. If a time-consuming task in the program can run asynchronously or in parallel, the throughput and interactivity of the whole program will be greatly improved. Modern PCs have multiple CPUs or multiple cores in a CPU. Whether we can reasonably use the ability of multiple cores will become the key to a large-scale application.

Basic thread usage

There are two ways to write the code executed by the thread Runtime: one is to create an instance of the thread subclass and rewrite the run method; the other is to implement the runnable interface when creating the class. Of course, the implementation of callable is also a way. The combined implementation of callable and future can obtain the return value after the task is executed, while the runnable and thread methods cannot obtain the result after the task is executed.

Once the thread is started, the start () method will return immediately instead of waiting for the run () method to return after execution, just as the run method is executed on another CPU.

Note: the common error when creating and running a thread is to call the thread's run () method instead of the start () method, as shown below:

At first you don't feel anything wrong, because the run () method is called as you want. However, in fact, the run () method is not executed by the newly created thread, but by the current thread. That is, it is executed by the thread executing the above two lines of code. If you want the new thread to execute the run () method, you must call the start method of the new thread.

Callable and future are combined to obtain the return value after executing the task:

Set the thread name for the thread:

When creating a thread, you can give the thread a name. It helps us distinguish between different threads.

volatile

Synchronized and volatile play an important role in multithreaded concurrent programming. Volatile is a lightweight synchronized, which ensures the "visibility" of shared variables in multiprocessor development. Visibility means that when one thread modifies a shared variable, another thread can read the modified value. It is less expensive than synchronized in some cases, but volatile does not guarantee the atomicity of variables.

When the volatile variable is written (there is a lock instruction under the assembly), the lock instruction has two functions in the multi-core system:

The cache consistency principle is followed in multi CPUs. Each CPU checks whether its cache value has expired by sniffing the data propagated on the bus. When it is found that the memory address corresponding to the cache has been modified, set the corresponding cache line to invalid state, and the next data operation will be re read from the system memory. For more volatile knowledge, click to deeply analyze the implementation principle of volatile.

synchronized

Synchronized has always been a veteran role in multithreaded concurrent programming. Many people will call it heavyweight lock, but with the development of Java SE1 6 after various optimizations on synchronized, it is not so heavy in some cases.

Every object in Java can be used as a lock. When a thread attempts to access a synchronized code block, it must first get the lock, and release the lock when exiting or throwing an exception.

The synchronized keyword cannot be inherited, that is, the synchronized method in the base class is not synchronized by default in the subclass. When a thread attempts to access a synchronized code block, it must first obtain the lock and release the lock when it exits or throws an exception. Every object in Java can be used as a lock, so where does the lock exist? The lock is stored in the Java object header. If the object is of array type, the virtual machine uses 3 words (word width) to store the object header. If the object is of non array type, it uses 2 words to store the object header. For more synchronized knowledge, click synchronized in Java se1.6.

Thread pool

The thread pool is responsible for managing worker threads and contains a task queue waiting to be executed. The task queue of the thread pool is a runnable collection. The worker thread is responsible for fetching and executing runnable objects from the task queue.

Java provides four thread pools through executors:

The bottom layers of the above thread pools call ThreadPoolExecutor to create thread pools.

When submitting a new task to the thread pool, the processing flow is as follows:

reference resources:

1. Deeply analyze the implementation principle of volatile

  2、Java SE1. Synchronized in 6

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>